Ruby 在其中定义一个子类是非常规的吗';什么是家长班?

Ruby 在其中定义一个子类是非常规的吗';什么是家长班?,ruby,Ruby,在它的父类下定义一个子类是常规的吗 class Element class Div < Element end class Paragraph < Element end end 类元素 类Div

在它的父类下定义一个子类是常规的吗

class Element

  class Div < Element

  end

  class Paragraph < Element

  end

end
类元素
类Div<元素
结束
类段落<元素
结束
结束
还是让模块包含子类更合适

class Element

end

module Elements

  class Div < Element

  end

  class Paragraph < Element

  end

end
类元素
结束
模块元素
类Div<元素
结束
类段落<元素
结束
结束
或者在模块中创建一个“基类”并在同一模块中定义子类

module Element

  class Base

  end

  class Div < Base

  end

  class Paragraph < Base

  end

end
模块元素
阶级基础
结束
类Div
还是强制使用命名约定更好

class Element

end

class DivElement < Element

end

class ParagraphElement < Element

end
类元素
结束
类DivElement<元素
结束
类段落元素<元素
结束
似乎每个库都选择了不同的名称空间/命名约定

哪一种最好使用?

每种方法的优缺点是什么?

名称空间和继承用于不同的目的。使用名称空间将模块封装在另一个模块中。使用继承将另一个模块的方法/变量/常量用作默认值来定义模块


原则上,您可能希望一个模块既在同一个模块的名称空间内,又从同一个模块继承,但这取决于您的用例。没有讨论特定的用例,无法决定在您介绍的方法中哪种方法是最好的。

这是我多次遇到的问题-您有一些共享功能和使用它的几个不同的实现类-共享功能和实现类的名称空间具有相同的名称是很自然的

在第一个例子中,我从未遇到过在父类下定义子类的问题——除了有时会让团队中的其他开发人员感到困惑之外。因此,根据您的合作伙伴以及他们的偏好,我认为这种方法没有任何问题

如果名称有意义的话,我仍然更喜欢第二种方法,为名称空间使用不同的名称。如果没有,我会使用第一种方法

我会避免使用像
Base
这样的名称,因为在我看来,这种泛型名称鼓励您只在其中添加任何旧的东西,而描述类所做的事情的名称(希望)会让您在每次添加方法时都会想它是否真的属于那里

我真的不喜欢你的命名约定示例中的复合名称,我用一种模糊的感觉向自己证明这就像数据库规范化一样——每个字段(或类名)应该只包含一条信息


不管怎样,我希望这对你有帮助。除了我自己的经验之外,我真的无法从任何来源(由你来决定你是否认为这是“可信的”),因为我确实认为这个问题没有绝对的答案。这在很大程度上是主观的

TL;DR:实现这一点最传统、最好的方法是使用包含基类及其子类的模块。但是让我们回顾一下所有的事情

这方面官方消息来源不多;但是,使用模块来包含库、代码和类组是一种风格

超类中的子类 专业人士

  • 自包含:整个类系统包含在一个名称下
缺点:

  • 不自然:谁会想到在超类中寻找子类呢
在超类中包含子类实际上取决于具体情况。然而,这种方法的任何好处也可以通过模块方法实现。但实际上,这并没有做到。类在这里包含方法、实例变量、类方法等。但是类可以被认为是嵌套的最后一级——除非是非常特殊的情况,否则类中没有类

我认为这有意义的一种情况是,子类的唯一使用方式是通过超类,例如
Formatter
类,它具有内部子类,如
XML
PDF
,等等。假设您只通过执行
Formatter.new(:XML)
之类的操作来使用这些类。但是如果我们这样做的话,子类应该是私有的,并且外部世界无论如何都无法访问。在这一点上,继承是一种非常C++y的方式,一点也不鲁比

模块外的基类,模块内的子类 优点:

  • 我想不出有什么
缺点:

  • 暗示不关联:如果元素与其子元素不在同一名称空间中,那么除了名称之外,还有什么告诉我它是相关的呢
这种方法很不自然。它使它看起来好像
元素
与它的子元素无关,或者如果从不同的角度看,它的子元素是不需要处理的内部实现细节。无论哪种方式,它看起来都像是简陋、草率的命名和糟糕的代码结构规划。如果我用这个来阅读代码,我必须查看
元素
模块的内容,才能看到
元素
是子类化的——这不是最自然的事情

模块中的类和子类(最佳解决方案) 优点:

  • 包含:超类和所有元素类都包含在一个名称空间中,允许轻松导入、需要、迭代等。这也有助于元编程
  • 可包含:类可以轻松地
    包含到任何代码中
  • 清楚:
    元素
    和子类之间存在明显的关联。它们显然是一组功能
缺点:

  • 鼓励惰性命名:这确实鼓励您命名类,例如
    Base
    ,它们非常模糊
<
module Elements
  class Element; end
  class Div < Element; end
  #etc...
end
module Elements
  class Element; end
  class DivElement < Element; end
  #etc...
end