像下面这样在其父类下定义子类是惯例吗?
class Element
class Div < Element
end
class Paragraph < Element
end
end
还是让模块包含子类更合适?
class Element
end
module Elements
class Div < Element
end
class Paragraph < Element
end
end
或者在一个模块中创建一个“基”类并在同一个模块中定义子类?
module Element
class Base
end
class Div < Base
end
class Paragraph < Base
end
end
或者强制命名约定更好?
class Element
end
class DivElement < Element
end
class ParagraphElement < Element
end
似乎每个库都选择不同的命名空间/命名约定。
哪个最好用?
各自的优缺点是什么?
最佳答案
TL;博士 :最传统和最好的方法是使用包含基类及其子类的模块。但让我们回顾一下一切。
这方面的官方消息来源并不多;然而,使用模块来包含库、代码和类组是一种风格。
父类(super class)中的子类
优点 :
缺点:
在父类(super class)中拥有子类实际上取决于情况。然而,这种方法的任何好处也可以通过模块方法来实现。但在实践中,这并没有完成。类在这里包含方法、实例变量、类方法等。但是类可以被认为是嵌套的最后一层——除非是非常特殊的情况,否则类中没有类。
我认为这有意义的一种情况是使用子类的唯一方法是通过父类(super class),例如
Formatter
具有内部子类的类,如 XML
, PDF
等。假设您仅通过执行 Formatter.new(:xml)
之类的操作来使用这些类。 .但是如果我们这样做,子类应该是私有(private)的,并且无论如何都不能被外界访问。在这一点上,继承是一种非常 C++y 的方式,而不是 Rubyish。模块外的基类,内的子类
优点:
缺点:
这种方法非常不自然。它看起来好像
Element
与它的子级无关,或者如果换个角度来看,它的子级是不需处理的内部实现细节。无论哪种方式,它看起来都像是破旧、草率的命名和糟糕的代码结构规划。如果我使用它阅读代码,我必须查看 Elements
的内容。模块看到Element
根本就被子类化了——这不是最自然的事情。模块中的类和子类(最佳解决方案)
优点:
include
编入任何代码。 Element
之间存在明显关联和子类。它们显然是一组功能。 缺点:
Base
这是非常模棱两可的。 这是最好的方法。它使类成为一个整洁的包,同时仍然显示出明显的关联和明显的“在这里,使用我的
Div
类”(与子类中的策略相反)。此外,这对于元编程真的很有帮助,在元编程中,将所有内容都放在一个模块中对于使事情正常工作至关重要。最后,这适用于像 autoload
这样的结构。 , require_relative
, include
等。这些表明这就是语言被设计用来使用的方式。强制命名约定
优点:
Div
或 Para
通过将它们变成 DivElement
和 ParaElement
. 缺点:
这是一个非常,非常不好的解决方案。它鼓励编写缺乏组织和意义的草率、C 风格的代码。这些命名约定应该只在没有更好解决方案的语言中使用,而 Ruby 有很多更好的解决方案。即使在数组中定义所有类也比命名约定好。
注意:然而,如果你真的想要,你可以定义一个短名称的命名约定,如
Div
或 Para
只要你仍然将它们保存在一个模块中,那么它就是 Elements::DivElement
.但是,这违反了 DRY,我不建议这样做。结论
所以,你真的有两个选择。只需将所有内容放在一个模块中:
module Elements
class Element; end
class Div < Element; end
#etc...
end
或者,将所有内容放在具有命名约定的模块中:module Elements
class Element; end
class DivElement < Element; end
#etc...
end
出于清晰、标准方法的使用和元编程的原因,我建议使用前者。
关于ruby - 在其父类中定义子类是否非常规?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14967751/