在第153页,她对is-a和behaves-like的区别进行了区分。继承对应于is-a,而模块对应于behaves-like。但真正的区别是什么呢?这两种技术都是通过自动消息委托来依赖消息的,对吗?
在她在理解角色一章中使用的例子中,似乎主要的区别是模块更好地借给了鸭子类型,并被用来使看似陌生的实体适合某些角色?角色到底是什么?任何Schedulable都需要响应模块的接口,因此可以在任何只需要一个响应该接口的role的地方进行替换。
而在继承一章中,Metz似乎只是定义了一个层次结构,而没有同样关注于鸭子类型。以她的自行车为例,她解决了相关类型的问题,这些相关类型共享共同的行为,但具有具有某些专门化的子类。
然而,也存在一些共性。两者都将抽象行为提升到共享类或模块中。这两个类仍然具有实现相同接口的子类,这些接口可用于进行鸭子类型。那么真正的区别是什么呢?
与继承部分相比,模块部分更多地强调了鸭子类型。为什么会这样呢?
发布于 2018-06-16 07:49:54
有几点不同,但在某些方面它们的行为是相同的。主要的区别在于,模块可以包含临时的、混合的和匹配的模块,而您只能从单个类“继承”。但最终,混入和继承的实现是相同的:模块或类被添加到祖先链中,并用于在响应消息时查找方法。在继承的情况下,您正在定义的类被添加到祖先链的末尾。模块可以包含在链中的不同位置(通常就在您要扩展的类之前),但是一旦它们在那里,它们的行为是相同的。
另一个不同之处在于,继承更多地修改或定义初始化。(尽管使用模块可以做到这一点,但很少会出现这种情况)。如果你关心一个对象的初始状态,你可能想要使用继承。
至于鸭子类型,模块通常被认为类似于具有内置实现的java接口。在java中,因为所有的东西都是强类型的,所以你必须显式地声明一个对象是否会“嘎嘎”。接口可以做到这一点,并且是have的“类似行为”。模块是最接近ruby的东西。
一般来说,模块往往更易于使用,因为它们具有灵活性,但模块要抽象得多,并且必须比基类具有更大的关注点分离。
发布于 2018-06-16 10:43:29
我是这样看待它的。我是一个人,那么作为一个人,我就是一个人。我的妻子也是一个人,但她是一个女人,但我们都扮演父母的角色。父母不是男人或女人,而是扮演特定角色的人。因此,定义该行为的代码可以放在一个模块中,并由两个类共享。
大多数现代语言都有扩展的概念,可以将常见行为添加到现有的类中。还有更多的例子,但Kotlin和Swift都在他们的标准库中利用了这一点,他们通过重用在一个地方定义的代码将公共行为添加到许多类中。
Java在为接口添加默认实现时也加入了这个概念。
https://stackoverflow.com/questions/50883387
复制相似问题