82

有人可以解释Scala中的特征吗?与扩展抽象类相比,特征有什么优势?

4

7 回答 7

80

简短的回答是您可以使用多个特征——它们是“可堆叠的”。此外,特征不能具有构造函数参数。

以下是特征的堆叠方式。请注意,特征的顺序很重要。他们会从右到左互相呼唤。

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
  }
}
于 2009-08-04T21:50:04.573 回答
19

站点提供了一个很好的特征使用示例。特征的一大优势是您可以扩展多个特征,但只能扩展一个抽象类。Traits 解决了多重继承的许多问题,但允许代码重用。

如果你了解 ruby​​,trait 类似于 mix-ins

于 2009-08-04T21:50:20.157 回答
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) {
}
输出 :

列表(我是雷
,我是雷,这是糟糕的一天!
,我是雷,今天是美好的一天!
,我是雷,这是糟糕的一天!
,我是雷,今天是美好的一天!
)

于 2014-08-30T23:29:34.103 回答
4

这是我见过的最好的例子

Scala 实践:组合特征 - 乐高风格: http: //gleichmann.wordpress.com/2009/10/21/scala-in-practice-composing-traits-lego-style/

    class Shuttle extends Spacecraft with ControlCabin with PulseEngine{

        val maxPulse = 10

        def increaseSpeed = speedUp
    }
于 2012-07-09T12:30:45.317 回答
3

特征对于将功能混合到类中很有用。看看http://scalatest.org/。请注意如何将各种特定领域语言 (DSL) 混合到测试类中。查看快速入门指南以了解 Scalatest ( http://scalatest.org/quick_start )支持的一些 DSL

于 2012-12-18T03:32:08.813 回答
2

与 Java 中的接口类似,特征用于通过指定支持的方法的签名来定义对象类型。

与 Java 不同,Scala 允许部分实现特征;即可以为某些方法定义默认实现。

与类相比,特征可能没有构造函数参数。特征类似于类,但它定义了函数和字段的接口,类可以提供具体的值和实现。

特征可以从其他特征或类继承。

于 2013-11-28T05:05:06.240 回答
1

我引用了Programming in Scala, First Edition一书的网站,更具体地说,是第 12 章中名为“ To trait, or not to trait? ”的部分。

每当您实现可重用的行为集合时,您都必须决定是要使用特征还是抽象类。没有固定的规则,但本节包含一些需要考虑的指导方针。

如果该行为不会被重用,则将其设为具体类。毕竟这不是可重用的行为。

如果它可以在多个不相关的类中重用,请将其设为 trait。只有特征可以混合到类层次结构的不同部分。

上面的链接中有更多关于特征的信息,我建议你阅读完整的部分。我希望这有帮助。

于 2014-09-19T11:25:06.800 回答