# Scala: Static - Konstruktor??



## Siassei (12. Feb 2010)

Hallo,

besitzt Scala eigentlich sowas wie einen static-Konstruktor? ala
Java: static { /* was weiss ich */ }


----------



## Landei (16. Feb 2010)

Alles, was in Java static ist (von statischen imports und statischen inneren Klassen mal abgesehen), kann in Scala über Companion-Objekte ausgedrückt werden.


```
public class Caesar {
  
   private String name;
   public Caesar(String name) {
      this.name = name;
   }
   public void say() {
      for(String l : list) {
         System.out.println(l); 
      }
   }
   
   private static List<String> list = new ArrayList<String>();
   static {
      list.add("veni"); 
      list.add("vidi"); 
      list.add("vici"); 
   }
}
```

... wird also zu ...


```
class Caesar(val name:String) {
   def say():Unit = Caesar.list.foreach(println)
}

object Caesar {
   //Analog zu Java
   var list = List[String]()
   list += "veni"
   list += "vidi"
   list += "vici"

   //Oder besser gleich
   //val list = List("veni","vidi","vici")
}
```


----------



## Siassei (16. Feb 2010)

Servus Landei,

ich hätte ein Beispiel geben sollen


```
class Abc { 
  static int a;
  static {
    InputStream in = ...
    ....
    a = in.read()
   }
}
```

In Scala würde das bei mir so aussehen

```
object Abc {
  var a

  // call static
  myStaticKonstr

  def myStaticKonstr = {
    ....
  }
}
```

Die Scala-Lösung gefällt sowie so besser. Ich wollte nur wissen, ob Object einen Konstruktor wie der in Java besitzt?


----------



## Landei (16. Feb 2010)

Ja, allerdings nur einen parameterlosen Hauptkonstruktor, während Instanzen auch Konstruktor-Parameter und Nebenkonstruktoren wie def this(xy:Z) ... zulassen. Dein myStaticKonstr würde so zwar funktionieren, aber normalerweise schreibt man den Initialisierungscode einfach direkt in das Objekt oder die Klasse.

Auch wenn eine komplizierte Initialisierung nötig ist, braucht man kein var, sondern kann ausnutzen, dass Blocks in Scala einen Wert besitzen:

```
object Abc {
  val a = {
    InputStream in = ...
    ....
    in.read()
  }
}
```

Nützlich ist weiterhin, dass man auch Tupel zuweisen kann:

```
val (x,y) = {
      val loc = myFrame.getLocation
      (loc.x, loc.y)  
  }
```


----------



## Siassei (16. Feb 2010)

Ein bisschen Off-topic, noch eine Konstruktor Frage.

Was nutzt mir die Definition von this in einer Klasse?
Scala:

```
def this(a, b, c) = this(a, _, c)
```
Ist das eine Möglichkeit Standard-Parameter zu setzen, oder steckt da noch mehr dahinter?

Zudem stehe ich noch vor einen kleinen Problem. Ich konvertiere gerade meine BigInteger-Implementation nach Scala (reine Übung ;-) ). Dabei habe ich folgendes
Java:

```
public NumericArray(NumericArray n) ....
public NumericArray(int[] mag) ....
public NumericArray(int val) ....
public NumericArray(String s) ...
...
```

Muss ich das in ein Object auslagern oder kann ich in Scala etwas definieren, dass ich schreiben kann
Scala:

```
val big1 = new NumericArray("123")
val big2 = new NumericArray(222)
```


----------



## Landei (17. Feb 2010)

Also, zuerst einmal ist Scala anders, weil es zwischen dem Haupt- und Nebenkonstruktoren unterscheidet. Jeder Nebenkonstruktor muss (direkt oder indirekt) den Hauptkonstruktor aufrufen:


```
class Bla(a:String, b:String, c:String) {  //<--Hauptkonstruktor
   def this(a:String, b:String) = this(a,b,"cool")
   def this(a:String) = this(a,"ist","cool")
   def this() = this("Scala","ist","cool")
}
```

Für den Hauptkonstruktor wählt man normalerweise die "allgemeinste" Variante. In Scala 2.8 können viele Nebenkonstruktoren wegfallen, weil jetzt Default-Argumente unterstützt werden:


```
//Scala 2.8
class Bla(a:String = "Scala", b:String = "ist", c:String = "cool") { 
}
```

Für dein NumericArray hast du zwei Möglichkeiten, nämlich die oben gezeigte Haupt/Nebenkonstruktor-Variante, oder du hast nur eine Art, das Objekt zu erzeugen (also nur einen Hauptkonstruktor), bietest aber Factory-Methoden am Begleit-Objekt als "Hilfskonstruktoren" an, was insbesondere dann der bessere Weg ist, wenn keine Vererbung vorgesehen ist. Dabei nutzt man die Sonderstellung von Methoden namens "apply" aus (statt bla.apply(x,y) darf man bla(x,y) schreiben):


```
class NumericArray(int[] mag) {
}

object NumericArray { //<--Begleitobjekt, companion object
  def apply(n: NumericArray) = new NumericArray(n.mag)
  def apply(value: Int) = new NumericArray(Array(value))
  def apply(s: String) = new NumericArray(convertSomehowStringToIntArray(s))
}

//Aufrufe
//Hauptkonstruktor
val a = new NumericArray(Array(2,3,4,5))
//Factory-Methoden
val b = NumericArray(13)
val c = NumericArray("134957495749580569")
val d = NumericArray(c)
```


----------

