And*_*rei 5 ruby inheritance class
让我们假设我们需要为树(或者我们需要的其他一些对象来定义一个公共类来解决问题).由于我们的类结构可能非常复杂,我更喜欢在定义之后定义类方法.我们共同的阶级BaseTree
和我们的具体类之一Tree
是
class BaseTree
class BaseNode; end
class NodeA < BaseNode; end
end
class Container
class Tree < BaseTree; end
end
Run Code Online (Sandbox Code Playgroud)
定义类结构后,我们#initialize
为所有节点设置.
class BaseTree::BaseNode
def initialize x
p x
end
end
Run Code Online (Sandbox Code Playgroud)
如果我们测试它,那么一切都很好
Container::Tree::NodeA.new(1)
# => 1
Run Code Online (Sandbox Code Playgroud)
但是,如果之后我们按以下方式添加方法
class Container::Tree::NodeA
def some_method; end
end
Run Code Online (Sandbox Code Playgroud)
然后它打破了NodeA
和之间的继承BaseNode
!
Container::Tree::NodeA.new(2)
# ~> -:30:in `initialize': wrong number of arguments(1 for 0) (ArgumentError)
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我们必须明确定义它
class Container
class Tree < BaseTree
class NodeA < BaseNode; end # explicit inheritance
end
end
class Container::Tree::NodeA
def some_method; end
end
Run Code Online (Sandbox Code Playgroud)
或通过以下方式
class Container::Tree::NodeA < Container::Tree::BaseNode
def some_method; end
end
class Container::Tree::NodeA < BaseTree::BaseNode
def some_method; end
end
Run Code Online (Sandbox Code Playgroud)
最后一种方法只需要使用一次 - 我们第一次添加方法时,我们可以跳过父类以便以后定义
class Container::Tree::NodeA
def another_method; end
end
Run Code Online (Sandbox Code Playgroud)
之后它工作正常,但我发现它非常麻烦,特别是如果有很多树类型和许多不同的节点.
有更优雅的方式来做这样的定义吗?
小智 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
Run Code Online (Sandbox Code Playgroud)