一个班级应该知道它的子类吗?一个类是否应该执行特定于给定子类的操作?
我的直觉告诉我,这是一个糟糕的设计,似乎是某种反模式。
一个班级应该知道它的子类吗?一个类是否应该执行特定于给定子类的操作?
我的直觉告诉我,这是一个糟糕的设计,似乎是某种反模式。
Answers:
类的概念所隐含的答案是“否”。
无论您要处理的动作,数据或关系是所有子类的一部分,那么都应在超类中对其进行处理而不检查实际类型。或它仅适用于某些子类-那么您必须执行运行时类型检查才能做正确的事,只要其他人继承了父类,就必须更改超类(否则它可能会默默地做错事情),派生类中的更改可能会破坏未更改的超类等。
简而言之,您会遇到许多不良后果,这些后果通常足以使您无法立即拒绝此类解决方案。如果您的几个子类都做同样的事情,并且希望避免代码重复(实际上总是一件好事),那么更好的解决方案是引入一个中级类,所有这些子类都可以从中继承代码。
不仅应该是不知道,这根本不可能!通常,可以随时随地扩展类。它可以由编写时甚至不存在的类扩展。
一些语言允许扩展类由超类控制。在Scala中,一个类可以标记为sealed
,这意味着它只能由同一编译单元(源文件)中的其他类扩展。但是,除非这些子类也为 sealed
或,否则其他类final
可以进一步扩展这些子类。
在Scala中,这用于建模封闭代数数据类型,因此规范的Haskell List
类型:
data List a = Nil | Cons a (List a)
可以像这样在Scala中建模:
sealed trait List[+A]
case object Nil extends List[Nothing]
final case class Cons[+A] extends List[A]
并且您可以保证仅存在这两个子“类”,因为List
is sealed
不能在文件外部扩展,Cons
is final
根本不能扩展并且Nil
is object
不能扩展。
但这是一个特定的用例(通过继承建模代数数据类型),即使在这种情况下,超类实际上也不知道其子类。对于这种类型的用户而言,这更加保证了List
,如果他对Nil
and 进行区分大小写,那么他的身后Cons
将不会弹出任何其他选择。
abstract internal
成员。
简单回答是不。
它使代码变得脆弱,并破坏了面向对象编程的两个基本原理。
是的,有时。例如,当存在有限数量的子类时。甲访问者模式是这种方法的有用性的图示。
示例:某些定义明确的语法的抽象语法树(AST)节点都可以从Node
实现访问者模式以处理所有节点类型的单个类中继承。
Node
当然,基类不包含对其子类的任何直接引用。但是它包含accept
带有Visitor
参数的方法。并且每个子类都Visitor
包含一个visit
方法。因此,尽管Node
没有直接引用其子类,但它通过Visitor
接口间接“了解”它们。他们都通过它耦合在一起。
如果我为一家公司编写组件,后来我离开后,有人出于自己的目的扩展了它,是否应该告知我?
没有!
与类相同。相信你的直觉。