开发者

Extending Objects in Ruby

开发者 https://www.devze.com 2023-02-17 13:07 出处:网络
I want to extend the Nokohiri开发者_如何学运维::XML::Node object into my own unique object with custom behaviors (methods).

I want to extend the Nokohiri开发者_如何学运维::XML::Node object into my own unique object with custom behaviors (methods).

I have the following object:

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

and the 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

My question is about best Ruby practices and basic OOP in Ruby.

How can I get RDFNodeFactory.get_node("someid") to return an RDFNode instead of a Nokogiri::XML::Node? I used to use type casting in Java but we don't have that in Ruby.

Should I just modify Nokogiri::XML::Node class instead of extending it to a custom class? What is a more acceptable practice?


Instead of extending the Nokogiri::XML::Node class just to add one method, you should move the get_tag method and add it to the already existing Nokogiri::XML::Node using the concept of Open Classes. This would look like:

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

This is completely fine in terms of Ruby Standards, just be sure there aren't any side affects when adding this method to Nokogiri::XML::Node, such as get_tag already exists.

With regards to open class(under the assumption that there are no current conflicts) vs inheriting 3rd party libraries:

This is a valid fear, this is why you have to be very careful when you utilize open classes and updating 3rd party libraries. However if you think of it, if a library changes their code in such a way that it messes up your code... This will happen both when you use open classes or inherit from their code. When it all boils down, you have a dependency, and you must be careful no matter what.


Instance methods tied to object, not class, so there is no way to "cast" object to another class. But in ruby you can add methods to existing class:

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

Or even add method to single object:

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


A (sort of) solution I have is containment

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

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

Now I have preserved modularity but lost all the awesomeness of inheritance! Not perfect but it's a start. Perhaps there is some way improve on this (extend RDFNode with Nokogiri::XML::Node and make self = node for Nokogiri methods)?

0

精彩评论

暂无评论...
验证码 换一张
取 消