Was sind die Vorteile der Verwendung von Merkmalen gegenüber abstrakten Klassen?

81

Kann jemand bitte Eigenschaften in Scala erklären? Was sind die Vorteile von Merkmalen gegenüber der Erweiterung einer abstrakten Klasse?

Zack Marrapese
quelle

Antworten:

80

Die kurze Antwort lautet, dass Sie mehrere Merkmale verwenden können - sie sind "stapelbar". Außerdem können Merkmale keine Konstruktorparameter haben.

So werden Merkmale gestapelt. Beachten Sie, dass die Reihenfolge der Merkmale wichtig ist. Sie rufen sich von rechts nach links an.

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
  }
}
André Laszlo
quelle
4
Das Fehlen von Konstruktorparametern wird fast durch die Verwendung von Typparametern in Merkmalen ausgeglichen.
Jus12
19

Diese Seite bietet ein gutes Beispiel für die Verwendung von Merkmalen. Ein großer Vorteil von Merkmalen ist, dass Sie mehrere Merkmale, aber nur eine abstrakte Klasse erweitern können. Merkmale lösen viele der Probleme mit Mehrfachvererbung, ermöglichen jedoch die Wiederverwendung von Code.

Wenn Sie Ruby kennen, ähneln die Eigenschaften Mix-Ins

Agilefall
quelle
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) {
}
Ausgabe :

Liste (Ich bin Ray
Ich bin Ray, es ist ein schlechter Tag!
Ich bin Ray, es ist ein wunderschöner Tag!
Ich bin Ray, es ist ein schlechter Tag!
Ich bin Ray, es ist ein wunderschöner Tag!
)

Mohan
quelle
3

Merkmale sind nützlich, um Funktionen in eine Klasse zu mischen. Schauen Sie sich http://scalatest.org/ an . Beachten Sie, wie Sie verschiedene domänenspezifische Sprachen (DSL) in eine Testklasse mischen können. In der Kurzanleitung finden Sie einige der von Scalatest unterstützten DSLs ( http://scalatest.org/quick_start ).

Todd Flandern
quelle
1

Ähnlich wie bei Schnittstellen in Java werden Merkmale verwendet, um Objekttypen durch Angabe der Signatur der unterstützten Methoden zu definieren.

Im Gegensatz zu Java können mit Scala Merkmale teilweise implementiert werden. dh es ist möglich, Standardimplementierungen für einige Methoden zu definieren.

Im Gegensatz zu Klassen haben Merkmale möglicherweise keine Konstruktorparameter. Merkmale sind wie Klassen, definieren jedoch eine Schnittstelle von Funktionen und Feldern, über die Klassen konkrete Werte und Implementierungen liefern können.

Merkmale können von anderen Merkmalen oder von Klassen erben.

Bao Luu
quelle
1

Ich zitiere aus der Website des Buches Programmierung in Scala, Erstausgabe und genauer gesagt aus dem Abschnitt " Zu Merkmalen oder nicht zu Merkmalen? " Aus Kapitel 12.

Wann immer Sie eine wiederverwendbare Sammlung von Verhalten implementieren, müssen Sie entscheiden, ob Sie ein Merkmal oder eine abstrakte Klasse verwenden möchten. Es gibt keine feste Regel, aber dieser Abschnitt enthält einige zu berücksichtigende Richtlinien.

Wenn das Verhalten nicht wiederverwendet wird, machen Sie es zu einer konkreten Klasse. Es ist schließlich kein wiederverwendbares Verhalten.

Wenn es in mehreren nicht verwandten Klassen wiederverwendet werden kann, machen Sie es zu einem Merkmal. Nur Merkmale können in verschiedene Teile der Klassenhierarchie gemischt werden.

Der obige Link enthält etwas mehr Informationen zu Merkmalen, und ich schlage vor, dass Sie den vollständigen Abschnitt lesen. Ich hoffe das hilft.

consuela
quelle