gpt4 book ai didi

Ruby:扩展模块的类

转载 作者:太空宇宙 更新时间:2023-11-03 17:06:14 25 4
gpt4 key购买 nike

我试图定义一个名为“HTML”的类来扩展 Nokogiri - 它使用模块。

我尝试了以下方法:

require 'nokogiri'

class HTML
include Nokogiri
end

require 'nokogiri'

class HTML
extend Nokogiri
end

但到目前为止,类HTML 不可能继承nokogiri 中的所有功能。所以像这样的东西不起作用:

doc = HTML.new
doc.HTML(open('http://www.google.com/search?q=tenderlove'))

# (NoMethodError) 的未定义方法“HTML”

有谁知道我如何设法编写一个继承模块所有方法的类?

最佳答案

Nokogiri 没有任何可继承的实例方法:

irb> Nokogiri.instance_methods
#=> []

但通常情况下,您会使用extend

% ri extend---------------------------------------------------------- Object#extend     obj.extend(module, ...)    => obj------------------------------------------------------------------------     Adds to obj the instance methods from each module given as a     parameter.        module Mod          def hello            "Hello from Mod.\n"          end        end        class Klass          def hello            "Hello from Klass.\n"          end        end        k = Klass.new        k.hello         #=> "Hello from Klass.\n"        k.extend(Mod)   #=> #<Klass:0x401b3bc8>        k.hello         #=> "Hello from Mod.\n"%

What you want to do is use all the class methods of the Nokogiri module as instance methods of your class. Which is a bit nonstandard, which is why the syntax doesn't support it. Most programmers use ruby modules for the Singleton pattern - there only needs to be one Nokogiri, so other things shouldn't be able to use its methods.

You could do some hacking with UndefinedMethods to get around this, but considering that Nokogiri has some compiled code in the backend, this may produce undefined bugs.

Which isn't to say you can't forward calls to Nokogiri:

# nokogiri_wrapper.rb
require 'rubygems'
require 'nokogiri'

class NokogiriWrapper
def method_missing(meth, *args, &blk)
puts "call for #{meth.inspect}, #{args}, #{blk ? "with block" : "and no block"}"
if Nokogiri.methods.include? meth.to_s
puts "forwarding to Nokogiri"
Nokogiri.send(meth, *args, &blk)
else
puts "falling back to default behaviour"
super
end
end
end

html = "<html></html>"

puts "calling Nokogiri directly"
p Nokogiri.HTML(html)

wrapper = NokogiriWrapper.new

puts "calling Nokogiri through wrapper"
p wrapper.HTML(html)

puts "calling non-Nokogiri method with wrapper"
p(begin
wrapper.scooby_dooby_doo!
rescue NoMethodError => e
[e.message, e.backtrace]
end)
% ruby nokogiri_wrapper.rbcalling Nokogiri directly<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><html></html>calling Nokogiri through wrappercall for :HTML, <html></html>, and no blockforwarding to Nokogiri<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><html></html>calling non-Nokogiri method with wrappercall for :scooby_dooby_doo!, , and no blockfalling back to default behaviour["undefined method `scooby_dooby_doo!' for #<NokogiriWrapper:0x581f74>", ["nokogiri_wrapper.rb:12:in `method_missing'", "nokogiri_wrapper.rb:29"]]

这是在 ruby​​ 中实现委托(delegate)模式的一种方法(另一种方法是使用其中一个委托(delegate)类)。

关于Ruby:扩展模块的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1067174/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com