试图了解 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
我是 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