我是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
提前致谢。
答案 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