ruby – 在它的父类中定义子类是不合常的吗?

在下面的父类下面定义一个子类是常规的吗?
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; DR:最常用和最好的方法是使用包含基类及其子类的模块.但是,让我们重温一切.

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

超类中的子类

优点:

>自包含:整个类系统包含在一个名称

缺点:

>不自然:谁会想到在超类中查找子类?

将子类置于超类中实际上取决于具体情况.但是,该方法的任何好处也可通过模块方法实现.但实际上,这还没有完成.类在这里包含方法,实例变量,类方法等.但是类可以被认为是最后一级嵌套 – 除非是非常特定的情况,否则类中没有类.

我能想到这个有意义的一种情况是,使用子类的唯一方法是通过超类,例如具有内部子类(如XML,PDF等)的Formatter类.假设您只使用这些类通过做Formatter.new(:xml)之类的事情.但是如果我们这样做,子类应该是私有的,无论如何都不能被外界访问.在这一点上,继承是一种非常方式,而不是Rubyish.

基类外部模块,子类内部

优点:

>我想不出任何

缺点:

> Implies Non-conected:如果Element与其子元素不在同一个命名空间中,超出名称内容告诉我它甚至是相关的?

这种方法非常不自然.它使得它看起来好像Element与它的孩子没有任何关系,或者如果用不同的方式看,它的子项是内部实现细节,不需要处理.无论哪种方式,它看起来像破旧,草率命名和糟糕的代码结构规划.如果我使用它来阅读代码,我必须查看Elements模块的内容,看看Element是否已经被子类化了 – 这不是最自然的事情.

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

优点:

> Contained:超类和所有Element类都包含在一个名称空间中,允许它们轻松导入,需要,迭代等.还有助于元编程.
> Includable:这些类可以很容易地包含在任何代码中.
>清除:Element和子类之间存在明显的关联.它们显然是一组功能.

缺点:

>鼓励懒惰的命名:这确实鼓励你为像Base这样非常模糊的类命名.

这是最好的方法.它使类成为一个整洁的包,同时仍然显示一个明显的关联和明显的“在这里,使用我的Div类”(而不是类中的子类策略).此外,这对于元编程非常有用,其中包含模块中的所有内容对于使事情有效至关重要.最后,这适用于autoload,require_relative,include等构造.这些表明这是语言的设计方式.

强制命名约定

优点:

>简单:这里没有复杂性.
>消除歧义:通过将它们转换为divelement和ParaElement来消除Div或Para等短名称的歧义.

缺点:

> Archaic:组类或方法的命名约定只应存在于没有更好方法的语言中,例如C或Objective-C.一旦获得名称空间,C就会删除它.
>没有编程分组:这些命名约定虽然对人类很清楚,但是对于元编程代码来说,类结构非常混浊,并且使得程序无法作为一个组来处理类.
>污染全局命名空间:这会在全局命名空间中创建许多名称,这总是一个坏主意.

这是一个非常非常糟糕的解决方案.它包含了编写草率,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

为了清晰,使用标准方法和元编程原因,我采用前者.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...