gpt4 book ai didi

class - 为什么 Scala 已经有了特性,它还有类?

转载 作者:行者123 更新时间:2023-12-03 14:40:20 25 4
gpt4 key购买 nike

这似乎是一个愚蠢的问题,所以请耐心等待...

考虑这个 REPL session :

scala> trait T
defined trait T

scala> val t = new T
<console>:8: error: trait T is abstract; cannot be instantiated
val t = new T
^

scala> val t = new T {}
t: java.lang.Object with T = $anon$1@78db81f3

scala> class C
defined class C

scala> val c = new C
c: C = C@170a6001

我们可以像使用类一样使用 trait,除了我们必须添加 {}new T 之后.事实上,我们实际上是在混合 T进入 java.lang.Object ,这对我来说实际上很有意义。

如果我们有成员,同样只有 {}必须添加:
scala> trait T2 { val s = "test" }
defined trait T2

scala> val t2 = new T2
<console>:8: error: trait T2 is abstract; cannot be instantiated
val t2 = new T2
^

scala> val t2 = new T2 {}
t2: java.lang.Object with T2 = $anon$1@6a688d6f

scala> t2.s
res0: java.lang.String = test

scala> class C2 { val s = "test" }
defined class C2

scala> val c2 = new C2
c2: C2 = C2@73ea7821

scala> c2.s
res1: java.lang.String = test

如果我们有抽象成员,那么特征声明实际上会缩短几个字符,更重要的是,在我看来更加一致(无需记住将 abstract 放在声明前面):
scala> trait T3 { val s: String }
defined trait T3

scala> val t3 = new T3 { val s = "test" }
t3: java.lang.Object with T3 = $anon$1@1f2f0ce9

scala> abstract class C3 { val s: String }
defined class C3

scala> val c3 = new C3 { val s = "test" }
c3: C3 = $anon$1@207a8313

如果您忘记必须定义一些成员,两种方式都会给您编译错误:
scala> val badt3 = new T3 {}
<console>:7: error: object creation impossible, since value s in trait T3 of type String is not defined
val badt3 = new T3 {}

scala> class BadC3 { val s: String }
<console>:8: error: class BadC3 needs to be abstract, since value s is not defined
class BadC3 { val s: String }

如果我们尝试做更复杂的事情,那么特质的力量自然会变得更加明显:
scala> val t4 = new T with T2
t4: java.lang.Object with T with T2 = $anon$1@479e0994

scala> val c4 = new C with C2
<console>:9: error: class C2 needs to be a trait to be mixed in
val c4 = new C with C2

所以我再次问,为什么 Scala 会在特性明显更简单和更强大的情况下为类而烦恼?

我认为原因是与 Java 的概念和实际兼容性,但我想知道是否可以在幕后维护代码兼容性。据我了解,Scala 特征只是在幕后成为 Java 类,那么为什么不能反过来发生,而 Scala 认为 Java 类本质上是特征呢?

与所有这些相关,为什么在不必要的时候不允许删除大括号?例如:
val t = new T

那时,作为用户,trait 将与当前的 Scala 类没有区别,但当然更好。

最佳答案

特质和类之间有几个区别:

  • 一个 trait 不能接受构造函数参数。这个限制可能会在某个时候解除,但这是一个难题。一个 trait 可以在层次结构中被多次继承,并且每个实例化都可以为构造函数参数提供不同的值
  • 一个 trait 被编译成一个 Java 接口(interface)和一个实现类(携带具体方法)。这意味着它有点慢,因为所有调用都通过接口(interface),如果它们是具体的,它们将被转发到它们的实现
  • 具有具体成员的特征不能在 Java 中很好地继承(可以,但它看起来像一个接口(interface),因此具体成员仍需要在 Java 中实现)。

  • 我认为类和特征之间的区别不会消失,主要是因为最后两项。但如果第一点得到解决,它们可能会变得更容易使用。关于没有 {} 的实例化,这是可以添加的便利,但我个人不喜欢它:每个实例化都会创建一个新的 类(class) (一个匿名的),并且应该向程序员表明情况就是这样。

    关于class - 为什么 Scala 已经有了特性,它还有类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8374992/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com