我试图在scala的上下文中理解Mixins。特别是我想知道继承概念和Mixins之间的区别。 Wiki说mixins和inheritance的概念之间有重要的区别,因此我想了解它。
Mixin的定义 维基 说:
mixin类充当父类,包含所需的功能。然后,子类可以继承或简单地重用此功能, 但不是专业化的手段。通常,mixin会将所需的功能导出到子类,而不会创建严格的单个“是”关系。这里有mixins和inheritance概念之间的重要区别,因为子类仍然可以继承父类的所有功能,但是, 关于孩子“成为一种”父母的语义不必一定适用。
在上面的定义中,我无法理解以粗体标出的语句。这是什么意思
- 子类可以在mixin中继承功能,但不能作为专业化的手段
- 在mixins中,子进程继承了父类的所有功能,但是关于子进程的语义“不是必须应用父进程”。 - 孩子如何延伸父母而不一定是父母?有这样的例子吗?
提前感谢您对上述内容的任何澄清。
我不确定我是否正确地理解了你的问题,但是如果我这样做了,你就会问一些东西如何能够继承,而不会像继承那样具有同样的意义。
但是,Mixins不是继承 - 它实际上更类似于动态地将一组方法添加到对象中。虽然继承说“这件事情是另一回事”,但是混合说,“这个对象有另外一些特征。”您可以在用于声明mixins的关键字中看到这一点: trait
。
从Scala主页公然窃取一个例子:
abstract class Spacecraft {
def engage(): Unit
}
trait CommandoBridge extends Spacecraft {
def engage(): Unit = {
for (_ <- 1 to 3)
speedUp()
}
def speedUp(): Unit
}
trait PulseEngine extends Spacecraft {
val maxPulse: Int
var currentPulse: Int = 0
def speedUp(): Unit = {
if (currentPulse < maxPulse)
currentPulse += 1
}
}
class StarCruiser extends Spacecraft
with CommandoBridge
with PulseEngine {
val maxPulse = 200
}
在这种情况下, StarCruiser
不是 CommandoBridge
要么 PulseEngine
;它 具有 但是,他们获得了这些特征中定义的方法。它 是 一个 Spacecraft
,正如您所看到的,因为它继承自该类。
值得一提的是,当一个 trait
延伸一个 class
,如果你想做点什么 with
这个特质,它必须扩展那个类。例如,如果我有一个 class Dog
,我没有 Dog with PulseEngine
除非 Dog
扩展 Spacecraft
。这样,它就像添加方法一样;然而,它仍然相似。
我认为它非常依赖于使用。 Scala是一种多范式语言,有时会让它变得强大而且有点令人困惑。
我认为当使用正确的方式时,Mixins非常强大。
Mixins应该用于引入行为并减少bolierplate。
Scala中的特性可以有实现,并且很有可能扩展它们并使用它们。
特征可以用于继承。它也可以称为mixins,但在我看来,这不是最好的使用方式 mixin
行为。在这种情况下,您可以将特征视为Java Abstract Classes。其中你得到的子类是超类(特征)的“类型”。
然而Traits可以用作 proper mixins
同样。现在使用特征作为 mixin
取决于“你如何混合它”的实现。主要是问自己一个简单的问题。它是“特质的子类真的是一个 kind
特征或是减少样板的特质行为中的行为“。
通常,最好通过将特征混合到对象而不是扩展特征来创建新类来实现。
例如,请考虑以下示例:
//All future versions of DAO will extend this
trait AbstractDAO{
def getRecords:String
def updateRecords(records:String):Unit
}
//One concrete version
trait concreteDAO extends AbstractDAO{
override def getRecords={"Here are records"}
override def updateRecords(records:String){
println("Updated "+records)
}
}
//One concrete version
trait concreteDAO1 extends AbstractDAO{
override def getRecords={"Records returned from DAO2"}
override def updateRecords(records:String){
println("Updated via DAO2"+records)
}
}
//This trait just defines dependencies (in this case an instance of AbstractDAO) and defines operations based over that
trait service{
this:AbstractDAO =>
def updateRecordsViaDAO(record:String)={
updateRecords(record)
}
def getRecordsViaDAO={
getRecords
}
}
object DI extends App{
val wiredObject = new service with concreteDAO //injecting concrete DAO to the service and calling methods
wiredObject.updateRecords("RECORD1")
println(wiredObject.getRecords)
val wiredObject1 = new service with concreteDAO1
wiredObject1.updateRecords("RECORD2")
println(wiredObject1.getRecords)
}
concreteDAO
是一个延伸的特征 AbstractDAO
- 这是继承
val wiredObject = new service with concreteDAO
-
这是适当的mixin行为
由于服务特征要求 mixin
一个 AbstractDAO
。这是错的 Service
扩展 ConcreteDAO
反正因为 service
需要 AbstractDAO
它不是一种类型 AbstractDAO
。
而是创建的实例 service
与不同的mixin。
一个 特征 (这就是所谓的 混入 当与类混合时)就像Java中的接口(虽然有很多 分歧)您可以在其中添加其他功能,而不必具有“是一种”关系。或者你可以这么说 通常 traits捆绑了可由多个独立类使用的功能。
举个例子来自Scala库, 有序[A] 是一个 trait
它为一些基本的比较操作提供了实现(比如 <
, <=
, >
, >=
)可以拥有自然排序数据的类。
例如,假设您有自己的课程 Number
和子类 EvenNumber
和 OddNumber
如下所示。
class Number(val num : Int) extends Ordered[Number] {
override def compare(that : Number) = this.num - that.num
}
trait Half extends Number {
def half() = num / 2
}
trait Increment extends Number {
def increment() = num + 1
}
class EvenNumber(val evenNum : Int) extends Number(evenNum) with Half
class OddNumber(val oddNum : Int) extends Number(oddNum) with Increment
在上面的例子中,类 EvenNumber
和 OddNumber
分享 是一个 有关系 Number
但 EvenNumber
没有“是”的关系 Half
也不 OddNumber
分享“是一种”与...的关系 Increment
。
另一个 很重要的一点 即使是上课 Number
使用 extends Ordered
语法,这意味着 Number
有一个 含蓄 是一个 与超类的关系 Ordered
即 Any
。
我认为它是在讨论实际的类层次结构。例如,a Dog
是一种类型 Animal
如果它从类扩展(继承)。它可以在任何地方使用 Animal
参数适用。