2009-04-29 7 views
19

Ich arbeite Scala lernen - aus einem C++ - Hintergrund kommen. Ich versuche , um eine kleine Klasse für eine Task-Tracking-App zu schreiben Ich hacker zusammen helfen Sie mir zu lernen, wie Scala zu programmieren.Verwenden Sie Klassenvariablen als Konstanten in Scala

Dies scheint, als ob es aus irgendeinem Grunde sollte einfach sein, aber es ist eluding ich:

package com.catenacci.tts 

class Task(val ID:Int, val Description:String) { 
val EmptyID = 0 
val EmptyDescription = "No Description" 

def this() = this(EmptyID,EmptyDescription) 
def this(ID:Int)={ 
    this(ID,EmptyDescription) 
} 
def this(Description:String)={ 
    this(EmptyID,Description) 
} 
} 

Ich versuche, drei Konstrukteuren zur Verfügung zu stellen: Aufgabe (ID, Beschreibung), Aufgabe (ID), Aufgabe (Beschreibung). In den letzten 2 Fällen möchte ich die Werte auf konstante Werte initialisieren, wenn einer der Werte nicht vom Aufrufer zur Verfügung gestellt wird. Und ich möchte in der Lage sein, dies außerhalb der Klasse für Unit-Tests zu überprüfen. Also habe ich mir gedacht, dass es zwei öffentliche Vals erlauben würde, außerhalb der Klasse zu überprüfen, sicher zu machen, dass mein Zustand ist, was ich erwarte.

Aus irgendeinem Grund wird dieser Code jedoch nicht kompiliert. Ich erhalte den folgenden Fehler:

error: not found: value EmptyID 

und

error: not found: value EmptyDescription 

Was bin ich dabei? Ich arbeite durch "Programmierung in Scala" so , wenn es eine einfache Antwort auf diese Frage gibt, bitte geben Sie mir Seite Zahlen. Es macht mir nichts aus zu lesen, aber mit dem Code auf Seite 60 und Seite 62 kann ich nicht sehen, warum dieser Code fehlschlägt.

Ich vermute, es hat etwas damit zu tun, dass diese Konstruktormethoden sind und dass möglicherweise die beiden Vals nicht bis zum Ende der Konstruktoren initialisiert werden. Wenn das der Fall ist, gibt es etwas Weg, um den Effekt zu bekommen, den ich suche?

+1

Siehe auch SIP 23 oder '42.type': http://stackoverflow.com/a/39065260/6309 – VonC

Antwort

38

Sie können die Konstanten in einem Begleitobjekt definieren:

object Task { 
val EmptyID = 0 
val EmptyDescription = "No Description" 
} 

Und dann als Task.EmptyID und Task.EmptyDescription verweisen.

Ich denke, Scala 2.8 hat Unterstützung für Standardwerte.

8

Siehe Germán für die Antwort. Dies geschieht, weil ein Konstruktor technisch Teil des statischen Bereichs ist. Mit anderen Worten, der Konstruktor kann nicht auf Instanzelemente zugreifen, da die Instanz noch nicht erstellt wurde. Alle "Klassenmitglieder" sind eigentlich Instanzmitglieder, weshalb der Code in der Frage nicht funktioniert. Germáns Antwort behebt dies, indem die beiden relevanten Werte in das Companion-Objekt verschoben werden, was sie zu statischen Mitgliedern der Klasse Task macht (nicht wirklich, aber man kann sich das so vorstellen).

+0

Danke - es ist gut zu wissen, warum das nicht so gut funktioniert hat und wie man es beheben kann. –

+0

Ja. Eine Weile lang habe ich mich gefragt, warum das in Java mit dem klassischen "Public Static Final" kein Problem war - es liegt an der Statik. –

1

In "Programmierung in Scala", siehe Abschnitt 6.7, wo die Verkettung von Konstruktoraufrufen erklärt wird. Der primäre Konstruktor wird als "der einzige Einstiegspunkt einer Klasse" beschrieben.