抽象クラスよりも特性を使用することの長所は何ですか?


81

誰かがScalaの特徴を説明できますか?抽象クラスを拡張することに対するトレイトの利点は何ですか?

回答:


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
  }
}

4
コンストラクターパラメーターの欠如は、ほとんどの場合、トレイトの型パラメーターを使用して補われます。
jus12 2011年

19

このサイトは、特性の使用法の良い例を示しています。トレイトの大きな利点の1つは、複数のトレイトを拡張できますが、抽象クラスは1つだけです。特性は、多重継承に関する問題の多くを解決しますが、コードの再利用を可能にします。

あなたがルビーを知っているなら、特性はミックスインに似ています


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) {
}
出力:

リスト(私はレイです
、私はレイです、それは悪い日です!
、私はレイです、それは美しい日です!
、私はレイです、それは悪い日です!
、私はレイです、それは美しい日です!
)




1

Javaのインターフェースと同様に、トレイトは、サポートされているメソッドのシグニチャーを指定することによってオブジェクトタイプを定義するために使用されます。

Javaとは異なり、Scalaではトレイトを部分的に実装できます。つまり、一部のメソッドのデフォルトの実装を定義することが可能です。

クラスとは対照的に、トレイトにはコンストラクターパラメーターがない場合があります。トレイトはクラスに似ていますが、クラスが具体的な値と実装を提供できる関数とフィールドのインターフェースを定義します。

トレイトは、他のトレイトまたはクラスから継承できます。


1

私は、 『Programming in Scala、First Edition』という本のWebサイトから引用しています。具体的には、第12章の「特性化するかしないか」というセクションを引用しています。

再利用可能な動作のコレクションを実装するときはいつでも、トレイトまたは抽象クラスのどちらを使用するかを決定する必要があります。確固たるルールはありませんが、このセクションには考慮すべきいくつかのガイドラインが含まれています。

動作が再利用されない場合は、それを具象クラスにします。結局、再利用可能な動作ではありません。

無関係な複数のクラスで再利用される可能性がある場合は、それを特性にします。クラス階層のさまざまな部分に混合できるのは、特性のみです。

特性に関する上記のリンクにはもう少し情報があります。セクション全体を読むことをお勧めします。これがお役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.