尝试理解 Scala 特性

问题描述 投票:0回答:4

我是 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 interface traits
4个回答
4
投票

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


2
投票

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


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

学习愉快!


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

进行链接
© www.soinside.com 2019 - 2024. All rights reserved.