Ich lerne immer noch Scala, aber eine Sache, die ich interessant fand, ist, dass Scala die Grenze zwischen Methoden und Feldern verwischt. Zum Beispiel habe ich eine Klasse wie folgt bauen ...Scala Eigenschaften Frage
class MutableNumber(var value: Int)
Der Schlüssel hier ist, dass der var im Konstruktor-Argumente automatisch erlaubt es mir, das ‚Wert‘ Feld wie ein Getter/Setter in Java zu verwenden.
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Wenn ich Einschränkungen hinzufügen möchten, kann ich so durch die Umstellung auf Methoden anstelle der instanz Feldern:
// require all mutable numbers to be >= 0
class MutableNumber(private var _value: Int) {
require(_value >= 0)
def value: Int = _value
def value_=(other: Int) {
require(other >=0)
_value = other
}
}
Die Client-Seite Code nicht bricht, da die API doesn 't change:
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Mein Auflegen ist mit der Named-Parameter-Funktion, die Scala-2.8 hinzugefügt wurde. Wenn ich benannte Parameter verwende, ändert sich meine API und es tut brechen die API.
val num = new MutableNumber(value=5) // old API
val num = new MutableNumber(_value=5) // new API
num.value = 6
println(num.value)
Gibt es eine elegante Lösung? Wie sollte ich meine MutableNumber-Klasse entwerfen, damit ich später Einschränkungen hinzufügen kann, ohne die API zu unterbrechen?
Danke!
Interessante ändern! Indem ich den Konstruktor verberge, zwinge ich alle dazu, das Companion-Objekt zu verwenden. Was, wenn ich MutableInteger selbst zu einer Fallklasse machen wollte?Ich weiß, dass Scala, wenn ich nur 'case' vor die Klassendefinition setze, automatisch das Begleitobjekt für mich erstellt ... würde diese Lösung noch funktionieren? – shj
Ja, wenn Sie ein explizit definiertes Companion-Objekt für eine Fallklasse haben, werden die Elemente dieses Objekts mit dem generierten Objekt verschmolzen (und können überschrieben werden, wenn Sie beispielsweise eine optimierte Methode 'Companion.apply()' bereitstellen möchten aber behalte das automatisch generierte 'unapply'). –
@shj - Nein, das würde nicht funktionieren, weil Fallklassen direkten (nicht geschützten) Zugriff auf die Konstruktorvariablen annehmen. Sie tun dies, weil Sie Wächter (in diesem Fall 'require (_value> = 0)) wollen. –