在Ruby中扩展对象

时间:2011-03-15 18:41:53

标签: ruby

我希望使用自定义行为(方法)将Nokohiri::XML::Node对象扩展为我自己的唯一对象。

我有以下对象:

class RDFNode < Nokogiri::XML::Node
  def get_tag
    self.at_xpath("Path/to/tag")
  end
end

和Node Factory:

class RDFNodeFactory
  @doc = Nokogiri::XML.parse('rdf_file.xml')

  def self.get_node(id)
    @doc.xpath_at("Path/to/rdf/node[@id=#{id}]")
  end
end

我的问题是Ruby中的最佳Ruby实践和基本OOP。

如何让RDFNodeFactory.get_node("someid")返回RDFNode而不是Nokogiri::XML::Node?我以前在Java中使用类型转换,但我们在Ruby中没有。

我应该修改Nokogiri::XML::Node类而不是将其扩展到自定义类吗?什么是更可接受的做法?

3 个答案:

答案 0 :(得分:3)

您应该移动get_tag方法并使用Open Classes.的概念将其添加到已存在的Nokogiri::XML::Node,而不是仅仅为了添加一个方法来扩展Nokogiri::XML::Node类,这看起来像:

class Nokogiri::XML::Node
  def get_tag
    self.at_xpath("Path/to/tag")
  end
end

这在Ruby标准方面完全没问题,只是确保在将此方法添加到Nokogiri :: XML :: Node时没有任何副作用,例如get_tag已经存在。

关于公开课(假设没有当前的冲突)与继承第三方图书馆的对比:

这是一种有效的恐惧,这就是为什么在使用开放类和更新第三方库时必须非常小心。但是,如果你想到它,如果一个库改变了它们的代码,它会弄乱你的代码......当你使用开放类或从代码继承时,这将发生。当这一切都归结为时,你就会有依赖性,无论如何都必须小心。

答案 1 :(得分:1)

实例方法绑定到对象,而不是类,因此无法将对象“转换”为另一个类。但是在ruby中,您可以向现有类添加方法:

class Nokogiri::XML::Node
  def get_tag
    self.at_xpath("Path/to/tag")
  end
end

甚至可以将方法添加到单个对象:

def @doc.get_tag
  self.at_xpath("Path/to/tag")
end

答案 2 :(得分:0)

我所拥有的(某种)解决方案是遏制

class RDFNode
  attr_reader :node
  def initialize(node)
    @node = node
  end

  def get_tag(id)
    node.at_xpath("Path/to/tag")
  end
end

现在我保留了模块化但却失去了继承的所有功能!不完美,但这是一个开始。也许有一些改进方法(用Nokogiri :: XML :: Node扩展RDFNode并为Nokogiri方法创建self = node)?