为什么Scala特质不允许构造函数参数?

6

我是从Java转换到Scala的新手,最近在阅读Traits方面的文章时经常看到一句话:Traits不能有构造器参数(不会?不应该?)。我很好奇是否有特别的原因导致这种情况。

作为一个数学/计算机科学背景多年以前的人,我想知道这是否是由于某些语言设计决策而不可避免的后果,还是出于避免某些继承/混入问题或其他原因而有意决定的?

希望有人能解答,因为这似乎背后可能隐藏着一些有趣的事情。


考虑到你可以通过覆盖vals并延迟执行构造函数的其余部分来模拟构造函数参数,我怀疑这背后没有深层次的原因。当然,也许有。也许与Java/Scala互操作有关? - Cubic
特性没有构造函数,这基本上是类和特性之间的区别。 - Martijn
相关:https://dev59.com/JXE85IYBdhLWcg3wYSdk - Michael Zajac
6个回答

11
其他答案描述了这门语言;我猜想你的问题可能真正想问的是“为什么要以这种方式设计”。我认为这是由于在扩展多个特征时,特别是在覆盖和类型以及各种混入策略方面,会出现不便和啰嗦的情况。Cake模式通常会导致各种特征在混合类中以完全不可见的方式提供彼此缺失的部分。并且混合可以是双向的,使用self-types。因此,从特征构建类对于编译器来说可能是一个非常混乱的过程。Scala经常为了语言使用和代码减少而交换编译器设计和实现的简单性,这无疑是一个很好的例子。因此,虽然可能存在简单的层次结构情况,其中拥有构造函数可能会很有用且足够,但对于更困难的非层次结构场景,它几乎肯定会与其他机制重复。

我不同意结论,但是因为你尝试回答问题(可能?)的本意,所以我给了+1。 - Madoc
@Madoc - 这是一个不够强的回答 - 我为所有的赞感到尴尬。希望像Daniel这样的人能够提供具体的意见。 - Ed Staub
1
你对我提问的意图是正确的 :) 谢谢。 - moncheery

5
Scala 3将允许使用特征参数。以下是来自文档的示例链接:docs
trait Greeting(val name: String) {
  def msg = s"How are you, $name"
}

class C extends Greeting("Bob") {
  println(msg)
}

3

2
特质(Traits)没有构造函数参数,因为特质不能被实例化。对于任何特质而言,都不可能创建一个类型完全为的对象。但是可以使用val重写trait defs,例如:
trait Foo {
  def bar: String
}
class Baz(override val bar: String) extends Foo

你不能直接构造它们,因为new MyTrait {}实际上是new Object with MyTrait {}的匿名类糖语法。


6
抽象类也适用相同的逻辑,是吗?我认为特质应该允许拥有构造函数,我也不明白为什么它们不能拥有构造函数。 - Madoc

0

Trait是Java接口的类比。主要区别在于Trait可以为其方法提供默认实现。

因此,Java接口无法具有构造函数,Scala Trait也是如此。


在Scala 3中,traits可以具有参数,因此这在Scala 3中无效。 - shvahabi

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接