2011-03-15 99 views
0

我想用自定义行为(方法)将Nokohiri::XML::Node对象扩展为我自己的唯一对象。在Ruby中扩展对象

我有以下对象:

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

和节点工厂:

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和基本OOP的红宝石。

我怎样才能让RDFNodeFactory.get_node("someid")返回RDFNode而不是Nokogiri::XML::Node?我曾经在Java中使用类型转换,但在Ruby中我们没有。

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

回答

2

而不扩展Nokogiri::XML::Node类只需添加一个方法,你应该移动get_tag方法以及使用的Open Classes.概念将它添加到现有Nokogiri::XML::Node这看起来像:

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

这是红宝石Standa方面完全没问题rds,只要确保在向Nokogiri :: XML :: Node添加此方法时没有任何副作用,例如get_tag已存在。

至于公开课(在假设目前没有冲突)与继承的第三方库:

这是一个有效的恐惧,这就是为什么你必须非常小心,当你使用公开课并更新第三方库。然而,如果你想到它,如果一个库改变他们的代码,这样会弄乱你的代码......当你使用开放类或从他们的代码继承时,这会发生。当一切都结束时,你有依赖,无论如何你都必须小心。

+0

是的,我喜欢开放课,但他们有时会吓到我。对我来说,看起来如果你只是将方法添加到属于单独维护的gem的类中,那么你确实冒着破坏模块性的风险。 Nokogiri可能会更新,然后我的宝石/应用程序被打破。 这是一种合法的恐惧还是我是偏执狂? – BeMathis 2011-03-15 19:06:34

+0

我编辑了我的答案来表达这种恐惧。 – 2011-03-15 19:15:34

+1

添加反映您所做更改的测试对于避免打开课程时出现问题非常重要,这样一来,如果新版本的gem破坏了您的更改,您将会了解它。 – 2011-03-15 19:30:01

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 
0

A(排序)解决方案,我已经是遏制

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 =节点)?