试图了解scala特征

时间:2015-07-27 11:40:29

标签: scala interface traits

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

提前致谢。

4 个答案:

答案 0 :(得分:4)

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

你可以使用trait作为接口,你可以用它来存储一些实现,你只需用它来定义一个常见的超类型:

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()”。

答案 1 :(得分:2)

当您实例化一个特征时,您创建了一个扩展该特征的匿名类的实例,它的工作方式与在java中创建匿名接口类的方式相同。如果您在特性中有任何未实现的方法,则编译器会在您创建匿名类时强制您在现场实施它们。

答案 2 :(得分:1)

确实,您的代码应该可以正常工作并输出您提到的相同结果。然而,这里需要注意的重点是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()

快乐学习!

答案 3 :(得分:0)

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

链接特征