我是 Scala 新手。我没有正确理解 Scala 的特质。我读过它与 Java 接口类似,但方法不必是抽象的。但是我如何声明 Scala 特征并在以下代码中实例化它。以下代码运行良好。
trait fooable {
def foo: Unit = {
println("This is foo")
}
}
object Main {
def main(args: Array[String]): Unit = {
println("This is morking")
val foo = new fooable{}
foo.foo
}
}
输出:
This is morking
This is foo
Scala 特征比 Java 接口和抽象类更通用。
您可以使用特征作为接口,您可以使用它来存储一些实现,您可以使用它简单地定义一个公共超类型:
trait Message
case class Text(text: String) extends Message
case class Data(data: ByteString) extends Message
多个特征可以“混合”在一个类中:
class MyClass extends TraitA with TraitB with TraitC
任何与同名方法的冲突都可以通过简单的规则解决:最后一个特征优先。此代码:
trait TraitA { def print() { println("A") } }
trait TraitB { def print() { println("B") } }
trait TraitC { def print() { println("C") } }
new MyClass.print()
将打印“C”。
Scala 特征无法实例化。您在示例中创建了一个匿名类。如果您向特征添加抽象方法,它将无法编译。
不相关的注释: 在有副作用的方法中写大括号“()”是一个很好的做法。你的方法 foo 有一个副作用:它打印一些东西。所以你应该写“foo()”。
当你实例化一个特征时,你创建了一个扩展该特征的匿名类的实例,它的工作方式与在 java 中创建接口的匿名类相同。如果您在 fooable 特征中有任何未实现的方法,编译器会在您创建匿名类时强制您当场实现它们。
事实上,您的代码应该可以正常工作并输出与您提到的相同的结果。然而,这里要注意的重要一点是 TRAIT 永远不能被实例化。 Java 接口永远不能被实例化,这与概念相同。
当 scala 编译器注意到代码 foo = new fooable{} 时,它会在内部创建一个匿名类,该类扩展了你的 fooable 特征,因此它由于继承而继承了 foo() 方法。请参阅以下代码片段:
scala> val foo = new fooable{}
foo: fooable = $anon$1@277c0f21
因此,当您调用 foo.foo 时,它会在运行时调用匿名类(即 $anon$1@277c0f21)继承的方法 foo()。
同样的理解也适用于 Java,以下是完全合法的 java 代码:
Runnable r = new Runnable() {
public void run() {
System.out.println(" Cat");
}
};
r.run()
学习愉快!
Scala Trait 是抽象的,无法实例化。在上面的代码中,其实例化为
val foo = new fooable{}
而不是
val foo = new fooable()
花括号创建了一些匿名类,它不是
fooable
而是一个空的
什么是特质?
特征与任何其他语言的界面相似。 Scala 允许在定义和构造期间实例化特征。例如,如果我们有一个特质和一个抽象类
trait testTrait {
}
abstract class BaseClass {}
class Derive extends BaseClass with testTrait {
}
// ---------------------- OR----------------------
// Traits can be used during instantiation
class Derive extends BaseClass {
}
val classInst = new Derive with testTrait
特征也可以使用多个
with trait
进行链接