试图了解 Scala 特性

Trying to understand scala trait

我是 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

提前致谢。

当你实例化一个特征时,你创建了一个扩展该特征的匿名 class 的实例,它的工作方式与在 java 中创建接口的匿名 classes 相同。如果您在特征 fooable 中有任何未实现的方法,编译器会在您创建匿名 class.

时强制您当场实现它们

Scala 特征比 Java 接口和抽象 classes 更通用。

你可以将特征用作接口,你可以用它来存储一些实现,你可以简单地用它来定义一个通用的超类型:

trait Message
case class Text(text: String) extends Message
case class Data(data: ByteString) extends Message

多个性状可以是'mixed in'一个class:

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 特征。您在示例中创建了一个匿名 class。如果您向特征添加抽象方法,它将无法编译。

不相关的注释: 在有副作用的方法中写大括号“()”是一个好习惯。您的方法 foo 有一个副作用:它会打印一些东西。所以你应该写 "foo()".

事实上,您的代码应该可以正常工作并输出与您提到的相同的结果。然而,这里要注意的重要一点是 TRAIT 永远不会被实例化。它与 Java 接口永远无法实例化的概念相同。

当 scala 编译器注意到代码 foo = new fooable{} 时,它会在内部创建一个匿名 class 来扩展您的 fooable trait,因此它继承了 foo() 方法。请参阅以下代码片段:

scala> val foo = new fooable{}
foo: fooable = $anon@277c0f21

因此,当您调用 foo.foo 时,它会在运行时调用匿名的 class(即 $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()  

花括号创建了一些匿名的 class,它不是 fooable 而是一个空的

什么是特质?

特征类似于任何其他语言的接口。 Scala 允许特征在定义期间和构造期间被实例化。例如,如果我们有一个特征和一个抽象 class

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