假设我们需要为树(或我们需要的其他一些对象来定义问题)定义一个公共类。由于我们的类结构可能非常复杂,我更喜欢在定义之后定义类方法。我们的公共课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
然后它打破了NodeA
和BaseNode
!!
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
之后它工作正常,但我发现它非常麻烦,特别是如果有很多树类型和许多不同的节点。
有更优雅的方式来做这样的定义吗?
答案 0 :(得分:2)
你应该在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