我是Scala的新手,开始学习语言以获得乐趣,我仍然试图理解它 . 我对Scala特性的理解是它们就像java接口,除了一些方法可以有一个实现 .
Java 8添加的接口可以具有可以提供实现的默认方法 .
Java 8接口和Scala特性之间有什么相似之处和不同之处?
Java 8' default methods 和 Scala traits 的动机不同 .
引入前者是为了支持安全的API演进和有限形式的多重继承 . 通过利用Project Lambda中的函数式编程习惯,将 forEach(lambda) 方法添加到 java.util.Collection 接口而不改变所有可能的实现者(在不破坏向后兼容性的情况下实际上是不可能的)是有益的 . 作为副作用,这也提供了mixin composition的形式 .
forEach(lambda)
java.util.Collection
Scala特征从头开始设计为模块化组件组合的构建块 . 它们是多继承友好的,并且由于线性化对混合的评估顺序有严格的规则而没有diamond problem . 它们也支持state,可以引用实现类并限制哪种类型可以混合使用 . 查看Scala集合库,其中使用了特征 .
请注意,使用scala 2.12.0 RC1 (Sept. 2016), Trait 现在编译为接口 .Scala 2.12旨在最佳地利用Java 8的新功能
Trait
借助Java 8允许接口中的具体方法,Scala 2.12能够将特征编译为单个接口 . 之前,特征表示为一个包含方法实现和接口的类 . 请注意,编译器在幕后仍然具有相当多的魔力,因此如果要在Java中实现特征,则必须小心 . (简而言之,如果特征执行以下任何一个特性,其子类需要合成代码:定义字段,在主体中调用super,initializer语句,扩展类,依靠线性化来查找正确的超级特征中的实现 . )
请参阅scala PR 5003更多实施的差异 .
在相似性上,两者都可以有默认方法,
差异方面,我们可以只为实例添加特征,而不是为整个类添加特征 . 例:
trait A { def m = ??? } class B new B() with A
同样明智的我们可以继续在实例上添加特征层 .
3 回答
Java 8' default methods 和 Scala traits 的动机不同 .
引入前者是为了支持安全的API演进和有限形式的多重继承 . 通过利用Project Lambda中的函数式编程习惯,将
forEach(lambda)
方法添加到java.util.Collection
接口而不改变所有可能的实现者(在不破坏向后兼容性的情况下实际上是不可能的)是有益的 . 作为副作用,这也提供了mixin composition的形式 .Scala特征从头开始设计为模块化组件组合的构建块 . 它们是多继承友好的,并且由于线性化对混合的评估顺序有严格的规则而没有diamond problem . 它们也支持state,可以引用实现类并限制哪种类型可以混合使用 . 查看Scala集合库,其中使用了特征 .
请注意,使用scala 2.12.0 RC1 (Sept. 2016),
Trait
现在编译为接口 .Scala 2.12旨在最佳地利用Java 8的新功能
请参阅scala PR 5003更多实施的差异 .
在相似性上,两者都可以有默认方法,
差异方面,我们可以只为实例添加特征,而不是为整个类添加特征 . 例:
同样明智的我们可以继续在实例上添加特征层 .