web-dev-qa-db-ja.com

抽象クラスで特性を使用する利点は何ですか?

誰かがScalaの特徴を説明してもらえますか?抽象クラスの拡張に対する特性の利点は何ですか?

80
Zack Marrapese

簡単な答えは、複数の特性を使用できることです。それらは「スタック可能」です。また、トレイトにコンストラクターパラメーターを含めることはできません。

特性がどのように積み重ねられるかを次に示します。特性の順序が重要であることに注意してください。彼らは、右から左にお互いを呼び出します。

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
  }
}
79
André Laszlo

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

Rubyを知っている場合、特性はミックスインに似ています

19
agilefall
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) {
}
 Output:
 
 List(私はRay 
、私はRay、今日は悪い日です!
、私はRay、それは
、私はレイ、悪い日です!
、私はレイ、それは美しい日です!
)
 
5

これは私が見た中で最高の例です

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

特性は、機能をクラスに混在させるのに役立ちます。 http://scalatest.org/ をご覧ください。さまざまなドメイン固有言語(DSL)をテストクラスに混在させる方法に注意してください。 ScalatestでサポートされているDSLのいくつかについては、クイックスタートガイドをご覧ください( http://scalatest.org/quick_start

3
Todd Flanders

私は本のウェブサイトから引用していますScala、初版のプログラミング、より具体的には「 特性、またはtrait? "第12章から.

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

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

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

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

1
consuela

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

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

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

特性は、他の特性またはクラスから継承できます。

1
Bao Luu