Traits vs Java - Interfaces

Das nächstliegende Gegenstück zu einem Scala - Trait in Java sind dessen Interfaces. In einem Trait werden Methoden definiert, welche von den einbindenden Klassen definiert werden müssen bzw. die implementierende Klasse muss als abstract definiert werden, was verhindert, dass Instanzen dieser Klasse (z.B. mit new) direkt angelegt werden können. Weiter lassen sich in Traits, wie in Java Interfaces, Konstanten definieren.

Der größte Unterscheid zu Java Interfaces besteht darin, das in einem Trait Funktionen bzw. Methoden vollständig ausprogrammiert werden können. Die Tatsache, dass in Traits Methoden / Funktionen ausprogrammiert werden können, zeigt eine Verwandtschaft von Scala Traits zu abstrakten Klassen in Java. Der Hauptunterschied zwischen beiden ist, dass abstrakte Klassen in Java explizite Konstruktoren haben können, was bei Scala Traits nicht der Fall ist.

Das Einbinden eines Traits definiert einen Vertrag, den eine Klasse erfüllen muss. Durch das Einbinden kann diese Klasse als vom Typ des entsprechenden Traits angesehen werden, ohne dass der konkrete Typ der Klasse bekannt sein muss.

In diesem Tutorial wird für den englischspracheigen Begriff "mix in" der deutsche Begriff "einbinden" verwendet, auch wenn diese Begriffe sich nicht direkt ineinander übersetzen lassen.

Eingeleitet wird ein Trait mit dem Schlüsselwort trait gefolgt vom Namen des Traits. Innerhalb von geschweiften Klammern folgt der Inhalt des Traits.

trait MyTrait{
  val myVal = 42
  def method1
  def method2
}
itmapa.de - X2H V 0.18

Eine nicht abstrakte Klasse, welche das Trait MyTrait implementiert, muss die Methoden method1 und method2 definieren.



Traits erweitern / einbinden (engl. mix in)

Eine Scala Klasse kann beliebig viele Traits erweitern bzw. einbinden (engl. mix in) und somit deren Eigenschaften erben. Vorausgesetzt, dass eine Klasse von keiner anderen Klasse explizit durch die Verwendung des Schlüsselwortes extends abgeleitet wird, wird das erste Trait durch die Verwendung des Schlüsselwortes extends eingebunden. Alle weiter einzubindenden Traits werden mit Hilfe des Schlüsselwortes with eingebunden.

Das nachfolgende Quelltextbeispiel zeigt einige Varianten für das Einbinden / Erweitern von Traits.

trait MyTrait1 {
  def foo1 : Int
}
          
trait MyTrait2 {
  def foo2 : Int
}
          
class BaseClass {
  def foo3 : Int = 3
}
          
class MyClass1 extends MyTrait1 with MyTrait2{
  def foo1 : Int = 1
  def foo2 : Int = 2
}
          
class MyClass2 extends BaseClass with MyTrait1 with MyTrait2{
  def foo1 : Int = 1
  def foo2 : Int = 2
}
itmapa.de - X2H V 0.18



Funktionen / Methoden und Variablen definieren

Im Gegensatz zu Java - Interfaces können in Scala Methoden und Variablen ausprogrammiert werden. Dieser Umstand macht Scala Traits ähnlich zu abstrakten Klassen in Java. Im Gegensatz zu abstrakten Klassen in Java können einem Scala Trait keine Konstruktor Parameter übergeben werden.

Das nachfolgender Trait zeigt ein Trait, welches eine Konstante definiert und zwei Methoden, die eine implementierende Klasse implementieren muss. Weiterhin wird in dem Trait eine Variable y und eine Methode calculate definiert, die in implementierenden Klassen zur Verfügung stehen.

trait MyTrait2{
  val x = 3
  
  def testMethod(check: String)
  def testMethod2()
  
  var y = 3
  
  def calculate(x1: Int, x2: Int): Int = {
    val temp = 2*x1+x2
    3 * temp
  }
}
itmapa.de - X2H V 0.18