Einstieg

Die gängigste Art eine Funktion zu definieren ist diese als Bestandteil eines Objektes zu definieren. Derartige Funktionen werden auch als Methode bezeichnet1. Da Scala eine objektorientierte Sprache ist, sind Funktionen, welche nicht an ein Objekt gebunden sind (sie sind dementsprechend keine Methode) selber wiederum Objekte.

Bedingungen, die eine Funktion erfüllen muss um als Funktion zu gelten sind:

  • Eine Funktion ist frei von Seiteneffekten
  • Eine Funktion hat ein Ergebnis (nicht Unit)
  • Eine Funktion liefert für gleiche Argumente immer das gleiche Ergebnis

Die Deklaration einer Funktion beginnt mit dem Schlüsselwort def gefolgt vom Namen der Funktion. Nach dem Namen folgt in Runden Klammern die Parameterliste der Funktion. Hinter den Runden Klammern wird nach einem Doppelpunkt der Rückgabetyp der Funktion definiert. Abschließend folgt nach einem Gleichheitszeichen der Inhalt der Funktion, welcher bei mehreren Anweisungen durch geschweifte Klammern zu einer Blockanweisung zusammengefasst wird.

  def test(v: Int):Int={
    println(v)
    return v+1
  }
  
itmapa.de - X2H V 0.17

In Scala braucht das return Statement nur angegeben zu werden, wenn ohne diese Anweisung weiter Code ausgeführt würde. Der Rückgabewert einer Funktion ist immer das Ergebnis des zuletzt ausgeführten Ausdrucks. Demnach ist die nachfolgend aufgeführte Funktion test2 equivalent zur vorherigen Funktion test.

  def test2(v: Int):Int={
    println(v)
    v+1
  }
  
itmapa.de - X2H V 0.17

Besteht eine Funktion nur aus einer Anweisung, können wir die geschweiften Klammern des Methodenrumpfs auch weglassen. Dadurch lassen sich einfache Funktionen lesbarer und in kürzerer Schreibweise darstellen.

  def simpleFunction(v1: Int, v2: Int) : Int = (v1 + v2) * 3
  
itmapa.de - X2H V 0.17

In Scala hat jede Funktion einen Rückgabewert. Funktionen, deren Rückgabewert vom Typ () "Unit" ist, werden auch als Prozedur (engl. procedure) bezeichnet. Der einzige Sinn des Aufrufs einer Prozedur ist die Ausführung von Seiteneffekten. Prozeduren sind demnach nicht "funktional programmiert".

Funktionen, die andere Funktionen als Argument erwarten oder als Rückgabewert haben, werden als Funktionen höherer Ordnung (engl. higher-order functions) bezeichnet.

Methoden / Funktionsaufruf

Ist eine Funktion an ein Objekt gebunden (also eine Methode) erfolgt deren Aufruf durch Angabe des Objektes gefolgt von einem Punkt, worauf die aufzurufende Funktion angegeben wird.

  objectName.methodName(argument)
              

Möchten wir eine Methode eines Singleton- oder Companion Objektes (dt. Begleitobjekt) aufrufen, setzen wir anstatt der Instanzvariable den Objektnamen. Dieser Objektname repräsentiert das einzig bestehende Objekt diesen Typs.

  SingletonName.methodName(argument)
              

In Scala gilt die Regel, dass der Punkt zwischen Objekt und Methode nicht angegeben werden muss. Dies kann zu einer "natürlicheren" Schreibweise beitragen, die auch das nachträgliche Lesen vereinfacht. Die nachfolgende Aufrufart ist demnach auch zulässig:

  objectName methodName(argument)
              

Eine weitere Regel in Scala ist, das wenn eine Methode ein oder kein Argument hat, dann kann die dem Argument umgebene Klammer weggelassen werden. Enthält eine Methodensignatur mehr als ein Argument, kann zwar der Punkt weggelassen werden, aber die Klammern müssen angegeben werden.

  objectName methodName argument
              

Die zuletzt beschriebene Aufrufweise wird als Operatorschreibweise bezeichnet. Tatsächlich gibt es in Scala keine Operatoren. Sprachkonstrukte, die wie Operatorenaufrufe aussehen, sind Methoden-/Funktionsaufrufe in Operatorschreibweise.

Setter und Getter

Zum Einstieg zu Setter und Getter in Scala sehen wir uns zunächst folgenden Quelltext an.

  class A {
    var b = new B()
    println(b.value)
    b.value = "321"
    println(b.value)  
  }

  class B (){
    var value = "123"
  }

  
itmapa.de - X2H V 0.17

Es hat den Anschein als würde in Klasse A direkt auf das var value zugegriffen, was aber nicht der Fall ist. Der Scala Compiler hat automatisch einen Setter und einen Getter für value generiert.

Die Getter-Methode hat den gleichen Namen wie die zugeordnete Variable. Die Setter-Methode hat im obigen Beispiel folgende Form:

  def value_=(s: String)
              

Das Vorhandensein des Setters kann verdeutlicht werden, indem wir ihn explizit definieren:

  class A {
    var b = new B()
    println(b.value)
    b.value = "321"
    println(b.value)  
  }

  class B (){
    var value = "123"
      
    def value_=(s: String)
  }
  
itmapa.de - X2H V 0.17

Versuchen wir diesen Quelltext zu kompilieren erhalten wir folgende Fehlermeldung:

  C:\test>scalac Test.scala
  A.scala:4: error: ambiguous reference to overloaded definition,
  both method value_= in class B of type (x$1: java.lang.String)Unit
  and  method value_= in class B of type (s: String)Unit
  match argument types (java.lang.String)
    b.value = "321"
      ^
  A.scala:11: error: method value_= is defined twice
    def value_=(s: String)
        ^
  two errors found
              

In vielen Fällen möchten wir jedoch beim Aufruf eines Setters oder Getters eingreifen und weitere Aktionen veranlassen. Für diesen Fall gehen wir einfach wie folgt vor. Wir definieren zunächst eine Variable, welchen den Wert speichern soll. Im nächsten Schritt definieren wir den Setter und den Getter in der Form, wie diese vorher automatisch generiert wurden. Ein weiteres Eingreifen an anderen Stellen des Quelltextes eines Programms ist nicht notwendig, da die Setter und Getter genauso vorliegen, wie es bei den automatisch generierten der Fall war. Im nachfolgenden Beispiel ist in Klasse B die beschriebene Vorgehensweise angewendet worden.

  class A {
    var b = new B()
    println(b.myValue)
    b.myValue = "321"
    println(b.myValue)  
  }

  class B (){
    private[this] var _myValue = "123"
    
    def myValue_= (s: String){
      println("setter Method called")
      _myValue = s
    }
    def myValue : String = _myValue
  }
  
itmapa.de - X2H V 0.21

Variable Parameterzahl / wiederholte Parameter

Der letzte (oder einzige) Parameter der Parameterliste einer Funktion kann als wiederholbar mit variabler Länge gekennzeichnet werden. Dies erlaubt, dass dieser Parameter einmal, keinmal oder beliebig oft im Funktionsaufruf angegeben werden kann. Die Kennzeichnung erfolgt, indem wir dem Parametertyp ein Asterisk (Sternchen) anhängen. Innerhalb der Funktion greifen wir auf den entsprechenden Parameter über ein Array des entsprechenden Typs zu. Das nachfolgende Beispiel zeigt zwei Funktionen mit variabler Parameterliste.

  object MainObject {
    def main(args: Array[String]) {
      val a = new A()
      a.demo1(1,2,3,4,5)
      a.demo1(6)
      a.demo2()
      a.demo2(7,8)
      a.demo2(9,10,11)
    }
  }

  class A{
    def demo1(value1: Int, value2: Int*) : Unit = {
      println(value1)
      value2.foreach(println)
    }
    
    def demo2(value1: Int*) : Unit = value1.foreach(println)
  }
  
itmapa.de - X2H V 0.17

Die Ausgabe des Programmes liefert:

  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
              

Auch wenn wir innerhalb der Funktion auf die variablen Parameter über ein Array zugreifen, können wir der Funktion kein Array (oder Seq z.B. List) direkt übergeben. Um den Compiler mitzuteilen, jedes Element einer Seq oder eines Arrays als einzelne Parameter zu verwenden, verwenden wir die Syntax: variablenName: _* in der Parameterliste. Das nachfolgende Beispiel zeigt die Vorgehensweise:

  object MainObject {
    def main(args: Array[String]) {
      val a = new A()
      
      val arr: Array[Int] = Array(1,2,3)
      val list: List[Int] = List(4,5,6)
      
      a.demo1(0,arr: _*)
      a.demo2(list: _*)
    }
  }

  class A{
    def demo1(value1: Int, value2: Int*) : Unit = {
      println(value1)
      value2.foreach(println)
    }
    
    def demo2(value1: Int*) : Unit = value1.foreach(println)
  }
  
itmapa.de - X2H V 0.17

Die Ausführung des Programmes führt zu folgender Ausgabe auf der Systemausgabe:

  0
  1
  2
  3
  4
  5
  6
              

Mehrere Parameterlisten

Methoden sind in Scala nicht auf eine Parameterliste beschränkt. Vielmehr können wir beliebig viele Parameterlisten definieren. Das nachfolgende Beispiel zeigt eine Funktion mit 3 Parameterlisten und deren Aufruf.

    def more(i: Int, j: Int)(k: Int)(m: Int): Int = i + j + k * m
    
    def main(args: Array[String]): Unit = {
      println(more(1,2)(3)(4))
    }
  
itmapa.de - X2H V 0.20

Weisen wir einer Variablen das Ergebnis einer Funktion zu und definieren nicht alle Parameterlisten, so erhalten wir eine neue Funktion mit den fehlenden Parameterlisten. Derartige Funktionen bezeichnen wir als "partiell angewendete Funktion" (engl. partial applied function). Um klarzustellen, dass wir eine derartige Funktion haben möchten, geben wir nach der zuletzt definierten Parameterliste einen Unterstrich an. Anstelle der Variablendefinition können wir die partiell abgeleitete Funktion auch direkt als Funktion definieren.

Das nachfolgende Beispiel soll die Definition partiell angewendeter Funktionen, einmal als Variablendefinition und einmal als Funktionsdefinition, zeigen.

  object Partially {

    def myFunction(a: Int)(b: Int)(c: Int): Int = {
      println("Hallo")
      a + b - c
    }
    
    val myPartial1 = myFunction(3)_
    def myPartial2 = myFunction(4)_
    
    def main(args: Array[String]): Unit = {
      println(myPartial1(3)(1))
      println(myPartial2(5)(1))
    }
  }
  
itmapa.de - X2H V 0.20

Das Curry Prinzip

Eine Funktion liegt in "currysierter" Form vor, wenn ihre Parameter einzeln in mehreren Parameterlisten (sofern mehrere Parameter vorhanden sind) vorliegen.

  def imCurried(a: Int)(b: Int)(c: Double): Double = a * b * c
  
itmapa.de - X2H V 0.20

Hat eine der Parameterlisten mehr als einen Parameter, liegt die entsprechende Funktion nicht in "currysierter" Form vor.

Das "Curry Prinzip" geht zurück auf ein Konzept des amerikanischen Mathematikers Haskell Brooks Curry und ermöglicht uns die Definition eigener Kontrollstrukturen. Nach Haskell Brooks Curry ist im Übrigen die funktionale Programmiersprache Haskell benannt.

Closures

Closures sind ein Element funktionaler Programmiersprachen. Ein Closure ist dabei ein Element, dass Zugriff auf seinen Erzeugungskontext hat.

Im nachfolgenden Quelltextbeispiel erzeugt die Funktion adderMaker ein Closure.

  def adderMaker(value: Int) = (x: Int) => value + x
  
itmapa.de - X2H V 0.21

Das hier erzeugte Closure ist die Funktion:

  (x: Int) => value + x
  
itmapa.de - X2H V 0.21

Der Zugriff auf den Erzeugungskontext geschieht im obigen Beispiel die Variable value, welche bei der Erzeugung des Closures festgelegt wird. Um mit dem Closure arbeiten zu können, ist es nicht notwendig, dass value im Sichtbarkeitsbereich der aktuellen Quelltextstelle liegt.

Im nächsten Beispiel sehen wir uns Closures in einer kleinen Anwendung an.

  object MyClosureApp {
    def main(args: Array[String]): Unit = {
      new MyClosureApp
    }
  }

  class MyClosureApp {
    def adderMaker(value: Int) = (x: Int) => value + x
    
    val adder1 = adderMaker(3)
    val adder2 = adderMaker(40)
    
    val adderHandler = new AdderHandler()
    adderHandler.handleAdder(adder1)
    adderHandler.handleAdder(adder2)
  }

  class AdderHandler {
    def handleAdder(f: Int => Int) = println(f(2))
  }

  
itmapa.de - X2H V 0.21

Im Beispiel haben wir ein Objekt object MyClosureApp, welche die Anwendung startet und eine Klasse des Typs class MyClosureApp erzeugt. Innerhalb der Klasse definieren wir die uns bekannte adderMaker Funktion, um Closures erzeugen zu können. Im Anschluss erzeugen wir zwei Closures adder1 und adder2 mit zwei unterschiedlichen Werten für value als Erzeugungskontext.

Die letzte Klasse AdderHandler stellt eine Funktion handleAdder zur Verfügung, welche eine Funktion Int => Int als Argument erwartet. Zum Abschluss der Klasse MyClosureApp erzeugen wir eine Instanz von AdderHandler und übergeben unsere Closures zur Ausgabe von Werten an die Methode adderHandler.

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

  5
  42
              

Benannte Argumente (engl. named arguments)

In Scala können die Argumente einer Funktion, wie bei Konstruktoren, über Ihren Namen übergeben werden. Werden die Argumente mit Ihrem Namen übergeben, ist die Reihenfolge, in der die Argumente angegeben werden, nicht mehr von Bedeutung. Das nachfolgende Beispiel zeigt die Anwendung benannter Argumente.

  object NamedArguments {
    def main(args: Array[String]) {
      doOutput(1,2)
      doOutput(x = 1, y = 2)
      doOutput(y = 1, x = 2)
    }
    
    def doOutput(x: Int, y: Int) : Unit = {
      println("x = " + x)
      println("y = " + y)
    }
  }
  
itmapa.de - X2H V 0.17

Der Ablauf des Programmes führt zu folgender Ausgabe auf der Systemausgabe:

  x = 1
  y = 2
  x = 1
  y = 2
  x = 2
  y = 1
              

Es ist auch möglich, eine Mischung aus Parameterangabe nach Parameterreihenfolge und benannten Argumenten zu machen. Wurde jedoch ein Argument benannt übergeben, müssen alle weiteren Parameter benannt übergeben werden. Das nachfolgende Programm zeigt beispielhaft diese Möglichkeit.

  object NamedArguments2 {
    def main(args : Array[String]) {
      doOutput(1,z = 2,y = 3)
    }
    
    def doOutput(x: Int, y: Int, z: Int) {
      println("x = "+x)
      println("y = "+y)
      println("z = "+z)
    }
  }
  
itmapa.de - X2H V 0.17

Die Ausführung des Programmes führt zu folgender Ausgabe auf der Systemausgabe:

  x = 1
  y = 3
  z = 2
              

Standardargumente (engl. default arguments)

In Scala ist es möglich für Argumente einer Funktion Standardwerte, wie bei Konstruktoren, festzulegen. Wird ein Argument beim Aufruf einer Funktion nicht angegeben, so wird der Standardwert verwendet. Das nachfolgende Beispiel gibt einen ersten Eindruck zur Verwendung von Standardargumenten.

  object StandardArgumente {
    def main(args: Array[String]) {
      standard1()
      standard1(3)
      standard1(4,5.0)
    }
    
    def standard1(v1: Int = 1, v2: Double = 2.0) {
      println(v1+" "+v2)
    }
  }
  
itmapa.de - X2H V 0.17

Auch wenn man Argumente mit Standardwerten verwendet, müssen nicht alle Argumente mit Standardwerten belegt werden. Es ist problemlos möglich, Argumente mit Standardwerten und Argumente ohne Standardwerte zu vermischen. Findet eine Mischung statt, so ist darauf zu achten, dass die Standardargumente möglichst am Ende der Argumentenliste definiert werden. Ist dies nicht der Fall, kommen die Standardwerte (außer beim Einsatz benannter Argumente) nicht zum Einsatz.

  object StandardArgumente2 {
    def main(args: Array[String]) {
      standard2(1)
      standard2(2,3.0)
      standard2(3,4.0,false)
    }
    
    def standard2(arg1: Int, arg2: Double = 2.0, arg3: Boolean = true) {
      println(arg1+" "+arg2+" "+arg3)
    }
  }

  
itmapa.de - X2H V 0.17

Funktionsliterale

Funktionen müssen nicht unbedingt an ein Objekt gebunden sein. Funktionen können auch direkt an der Stelle definiert werden, an denen Sie im Quelltext gebraucht werden. Derartige Funktionen sind Funktionsliterale in der Form2:

  (x: Int, y: Int) => x + y
              
Funktionsliteral

Funktionen höherer Ordnung (engl. higher-order functions)

Funktionen sind in Scala vollwertige Elemente. Da Scala eine "vollständig" objektorientierte Sprache ist, sind Funktionen in Scala Objekte. Funktionen können unter anderem

  • An andere Funktionen übergeben werden
  • Rückgabe einer anderen Funktion sein
  • An Variable gebunden werden

Nachfolgend ein Beispiel einer höheren Funktion, welche eine Funktion als Argument in der Parameterliste erwartet.

  def higherOrder(myFunction: (Int) => Int) = {}
  
itmapa.de - X2H V 0.17

Eingeleitet wird diese Funktion höherer Ordnung wie gewohnt mit dem Schlüsselwort def gefolgt vom Namen der Funktion higherOrder. In den Klammern hinter dem Namen folgt als Parameter eine Funktionsdefinition myFunction: (Int) => Int. Hierbei ist myFunction der Name der Funktion, wie Sie innerhalb von higherOrder angesprochen werden kann. Wie bei Variablen muss der Name der Funktion nicht mit dem Namen der übergebenden Funktion übereinstimmen. Nun folgt in Klammern die Parametersignatur-Definition, welche die übergebene Funktion aufweisen muss. Nach dem recht gerichteten Pfeil => folgt die Ergebnisdefinition, welche mit dem Ergebnistyp der übergebenen Funktion übereinstimmen muss. Das Gleichheitszeichen und die geschweiften Klammern runden das Beispiel zu einer vollständigen Funktionsdefinition ab.

Im nachfolgenden Beispiel wollen wir unsere Funktion derart erweitern, dass mit der übergebenen Funktion innerhalb der Funktion höheren Ordnung etwas geschieht. Im Beispiel geben wir einfach das Ergebnis der übergebenen Funktion auf der Systemausgabe aus.

  def higherOrder(myFunction: (Int) => Int) {
    println(myFunction(3))
  }
  
itmapa.de - X2H V 0.17

Und nun noch ein vollständiges Programm, wo zwei unterschiedliche Funktionen unserer Funktion höherer Ordnung übergeben werden.

  object GettingHigher {

    def main(args:Array[String]) {
      def function1 = (x: Int) => 3 * x
      def function2 = (y: Int) => 4 * y
      higherOrder(function1)
      higherOrder(function2)
    }
    
    def higherOrder(myFunction: (Int) => Int) {
      println(myFunction(3))
    }
  }
  
itmapa.de - X2H V 0.17

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

  9
  12
              

Besteht die Parameterliste der zu übergebenen Funktion aus nur einem Parameter, so kann die Klammer um den Parameter auch weggelassen werden.

  def higherOrder(myFunction: Int => Int) = {}
  
itmapa.de - X2H V 0.17

Enthält die Parametersignatur der zu übergebenen Function mehrere Parameter, so sind diese einfach durch ein Komma getrennt aufzulisten.

  def higherOrder(myFunction: (Int,Double,String) => Int) = {}

  
itmapa.de - X2H V 0.17

Datenkonsistenz

Das Objekt scala.Predef (API Flagge Großbritanien) enthät 6 Methoden (3 * 2 Signaturen) die zur Prüfung der Datenkonsistenz eingesetzt werden können:

  • final def assert(assertion: Boolean, message: ? Any): Unit
  • def assert(assertion: Boolean): Unit
  • final def assume(assumption: Boolean, message: ? Any): Unit
  • def assume(assumption: Boolean): Unit
  • final def require(requirement: Boolean, message: ? Any): Unit
  • def require(requirement: Boolean): Unit


Die Hauptaufgabe aller Methoden ist grundsätzlich gleich. Sie prüfen ob eine Bedingung gegeben ist und werfen im negativem Falle ein Throwable Objekt. assert und assume werfen im negativen Fall ein AssertionError wohingegen require eine IllegalArgumentException wirft.

Stellt sich nun die Frage, warum wir drei verschieden Methoden benötigen um eine Bedingung zur Laufzeit zu prüfen. Der Unterschied der Methoden liegt im Grund (warum der Programmierer prüft) des Aufrufs.

  • assert: Mit assert soll das eigentliche Programm (die Bibliothek) auf Korrektheit geprüft werden.
  • assume: Prüft das Programm wie assert auf Korrektheit, wobei hier Axiome geprüft werden sollen.
  • require: Mit require sollen Argumente eines Nutzers des Programmes (Bibliothek) auf Zulässigkeit geprüft werden.

Zusammenfassend kann gesagt werden, dass wenn assert oder assume negativ ausgewertet werden ein Fehler im Programm (Bibliothek) vorliegt. Wird require negativ ausgewertet so ist das Programm (Bibliothek) in Ordnung, nur die übergebenen Argumente sind nicht zulässig.

Die Methoden assert, assume und require kommen jeweils in 2 Ausprägungen. Einmal, wo nur die zu prüfende Bedingung übergeben wird und einmal, wo zusätzlich zur Bedingung noch eine "Message" übergeben wird, die im negativen Fall der Bedingung mit dem Throwable Objekt ausgegeben wird.

Nachfolgend ein Beispielprogramm zur Verwendung von assert.

  object MyFirstAssertion{
    def main(args: Array[String]): Unit = {
      val value1 = 42
      val value2 = 43
      assert(value1 == value2)
    }
  }
  
itmapa.de - X2H V 0.20

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

  Exception in thread "main" java.lang.AssertionError: assertion failed
  	at scala.Predef$.assert(Predef.scala:165)
  	at test.MyFirstAssertion$.main(Test.scala:8)
  	at test.MyFirstAssertion.main(Test.scala)
              

Im nachfolgenden Beispiel nehmen wir die gleiche Prüfung nochmals vor mit der Erweiterung, dass wir assert eine Message übergeben, die im negativen Fall ausgegeben werden soll.

  object MyFirstAssertion{
    def main(args: Array[String]): Unit = {
      val value1 = 42
      val value2 = 43
      assert(value1 == value2, "value1 = "+value1+"; value2 = "+value2)
    }
  }


  
itmapa.de - X2H V 0.20

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

  Exception in thread "main" java.lang.AssertionError: assertion failed: value1 = 42; value2 = 43
  	at scala.Predef$.assert(Predef.scala:179)
  	at test.MyFirstAssertion$.main(Test.scala:8)
  	at test.MyFirstAssertion.main(Test.scala)
              

Die nächste Variante verwendet anstatt assert require um die Datenkonsistenz zu prüfen.

  Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: value1 = 42; value2 = 43
  	at scala.Predef$.require(Predef.scala:233)
  	at test.MyFirstRequire$.main(Test.scala:8)
  	at test.MyFirstRequire.main(Test.scala)

  
itmapa.de - X2H V 0.20

Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:

  Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: value1 = 42; value2 = 43
  	at scala.Predef$.require(Predef.scala:233)
  	at test.MyFirstRequire$.main(Test.scala:8)
  	at test.MyFirstRequire.main(Test.scala)
              

Sichtbarkeit

Nicht immer wollen wir, dass unsere Funktionen/Methoden (ab jetzt kurz nur Methoden) überall sichtbar (erreichbar) sind. Um die Sichtbarkeit der Methoden einzuschränken helfen uns, wie bei Konstruktoren, die Sichtbarkeitsmodifizierer private und protected.

Dem Thema Sichtbarkeit ist aug ScalaTutorial.de ein eigenes Kapitel gewidmet.

Grundsätzlich kennen wir in Scala drei Ebenen der Sichtbarkeit:

  • public
  • protected
  • private


public:
Der Sichtbarkeitsbereich "public" (dt. öffentlich) ist in Scala Standard. Sofern keine Einschränkung mit private oder protected vorgenommen wird, ist die Sichtbarkeit der Methode öffentlich. Ein separate Sichtbarkeitsmodifizierer für öffentlich, ist in Scala nicht vorgesehen.

protected:
Der Sichtbarkeitsbereich protected (dt. geschützt) beschränkt den Sichtbarkeitsbereich der Methode auf die eigene Klasse und auf alle Klassen die von dieser Klasse abgeleitet sind.

private:
Der Sichtbarkeitsbereich private (dt. Privat) beschränkt die Sichtbarkeit auf die eigene Klasse.



Die Sichtbarkeitsbereiche für protected und private können noch feiner definiert werden.