使用traits相比抽象类有哪些优点?

82

请问有人能解释一下Scala中的特征(traits)吗?和继承抽象类相比,特征有什么优势?

7个回答

82

简而言之,您可以使用多个traits——它们是“可堆叠”的。此外,traits不能具有构造函数参数。

下面是traits是如何叠加的。请注意,traits的顺序很重要。它们将从右到左相互调用。

class Ball {
  def properties(): List[String] = List()
  override def toString() = "It's a" +
    properties.mkString(" ", ", ", " ") +
    "ball"
}

trait Red extends Ball {
  override def properties() = super.properties ::: List("red")
}

trait Shiny extends Ball {
  override def properties() = super.properties ::: List("shiny")
}

object Balls {
  def main(args: Array[String]) {
    val myBall = new Ball with Shiny with Red
    println(myBall) // It's a shiny, red ball
  }
}

4
在特质中,缺少构造函数参数的情况几乎可以通过使用类型参数弥补。 - Jus12
在Scala 3中,特质可以有参数。 - Gaël J

20

这个网站展示了一个良好的特征使用例子。Trait的一个重要优点是你可以继承多个Trait,但只能继承一个抽象类。Traits解决了许多多重继承的问题,同时允许代码重用。

如果您了解Ruby,Traits类似于Mix-ins。


5
package ground.learning.scala.traits

/**
 * Created by Mohan on 31/08/2014.
 *
 * Stacks are layered one top of another, when moving from Left -> Right,
 * Right most will be at the top layer, and receives method call.
 */
object TraitMain {

  def main(args: Array[String]) {
    val strangers: List[NoEmotion] = List(
      new Stranger("Ray") with NoEmotion,
      new Stranger("Ray") with Bad,
      new Stranger("Ray") with Good,
      new Stranger("Ray") with Good with Bad,
      new Stranger("Ray") with Bad with Good)
    println(strangers.map(_.hi + "\n"))
  }
}

trait NoEmotion {
  def value: String

  def hi = "I am " + value
}

trait Good extends NoEmotion {
  override def hi = "I am " + value + ", It is a beautiful day!"
}

trait Bad extends NoEmotion {
  override def hi = "I am " + value + ", It is a bad day!"
}

case class Stranger(value: String) {
}

输出:
列表(我是雷,今天不好!,我是雷,今天很美丽!,我是雷,今天不好!,我是雷,今天很美丽!)

4

3

2
与Java中的接口类似,特质用于通过指定支持方法的签名来定义对象类型。
与Java不同,Scala允许部分实现特质;即可以为某些方法定义默认实现。
与类相比,特质可能没有构造函数参数。特质类似于类,但定义了一个函数和字段的接口,类可以提供具体的值和实现。
特质可以继承自其他特质或类。

1
我引用了《Scala编程》第一版网站上的内容,具体来说是第12章中称为“使用Trait还是不使用Trait?”的部分。
无论何时你实现可重用的行为集合,都必须决定是要使用Trait还是抽象类。没有固定的规则,但本节包含了一些需要考虑的指导方针。
如果该行为不会被重用,则将其制作成一个具体类。毕竟它不是可重用的行为。
如果它可能在多个不相关的类中被重用,则将其制作成Trait。只有Trait可以混合到类层次结构的不同部分中。
上述链接中还有更多关于Traits的信息,建议您阅读完整部分。希望这可以帮助您。

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