【问题标题】:Ruby class inheritance and incremental definitionRuby 类继承和增量定义
【发布时间】:2011-03-30 01:27:50
【问题描述】:

假设我们需要为树定义一个公共类(或为了解决问题我们需要拥有的一些其他对象)。由于我们的类结构可能相当复杂,所以我更喜欢在定义类方法之后再定义它。我们的普通类BaseTree 和我们的特定类之一Tree

class BaseTree
  class BaseNode; end
  class NodeA < BaseNode; end
end

class Container
  class Tree < BaseTree; end
end

定义类结构后,我们为所有节点设置#initialize

class BaseTree::BaseNode
  def initialize x
    p x
  end
end

如果我们测试它,那么一切都很好

Container::Tree::NodeA.new(1)
# => 1

但是,如果之后我们通过以下方式添加一个方法

class Container::Tree::NodeA
  def some_method; end
end

那么它会破坏NodeABaseNode 之间的继承!!

Container::Tree::NodeA.new(2)
# ~> -:30:in `initialize': wrong number of arguments(1 for 0) (ArgumentError)

为了解决这个问题,我们必须明确定义它

class Container
  class Tree < BaseTree
    class NodeA < BaseNode; end # explicit inheritance
  end
end

class Container::Tree::NodeA
  def some_method; end
end

或通过以下方式

class Container::Tree::NodeA < Container::Tree::BaseNode
  def some_method; end
end

class Container::Tree::NodeA < BaseTree::BaseNode
  def some_method; end
end

最后一种方式只需要使用一次——第一次添加方法,以后定义可以跳过父类

class Container::Tree::NodeA
  def another_method; end
end

之后它工作正常,但我觉得它很麻烦,特别是如果有很多树类型和许多不同的节点。

有没有更优雅的方式来做这样的定义?

【问题讨论】:

  • 也许 ping 核心看看这是否是预期的
  • 我不明白你为什么使用类作为命名空间,我希望那里有模块。绑定似乎不匹配,但我不明白这里的问题。顺便说一句,您不定义类方法,而是定义实例方法。

标签: ruby class inheritance


【解决方案1】:

在 ruby​​ 中组织代码的方式是使用模块作为命名空间,以及子类的类继承和继承行为。我不认为 ruby​​ 支持命名空间继承(这基本上就是你说 Tree 从 BaseTree 继承并将 NodeA 引用为 Tree::NodeA 所做的),因此这种奇怪的边缘情况是绑定不正确的。

在任何情况下,我都不认为有一个有效的场景需要您按照呈现的方式组织代码。 “正确”的方式是通过定义命名空间的模块和定义行为的类来组织它。

因此,这样定义树的方法是仅声明类,不使用名称空间,或者使用名称空间将它们与我有名称冲突的类区分开来:

module UserInterface
  class Container; end

  class Tree; end

  class BaseTree < Tree; end

  class BaseNode; end

  class NodeA < BaseNode; end
end


module DataStructures
  class Tree; end

  class RedBlackTree < Tree; end
end 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 2015-12-09
    相关资源
    最近更新 更多