2009-11-17 8 views
7

Ich bin zu wollen, etwas zu tun, wie diese Unterklasse:Wie ein Objekt mit einem var in seinem primären Konstruktor

class A (var updateCount: Int) { 
} 

class B (val name: String, var updateCount: Int) extends A(updateCount) { 
    def inc(): Unit = { 
    updateCount = updateCount + 1 
    } 
} 

var b = new B("a", 10) 
println(b.name) 
println(b.updateCount) 

b.updateCount = 9999 
b.inc 
println(b.updateCount) 

aber der Compiler mag es nicht.

(fragment of extend.scala):5: error: error overriding variable updateCount in class A of type Int; 
variable updateCount needs `override' modifier 
class B (val name: String, var updateCount: Int) extends A(updateCount) { 

Das Hinzufügen von Override auf updateCount funktioniert auch nicht. Was ist der saubere Weg, dies zu tun?

+0

Ein paar Leute haben darauf hingewiesen, dass ich die Variable aus updateCount in B entfernen sollte. Das funktioniert nicht. Wenn Sie es versuchen, erhalten Sie (Fragment von extend.scala): 7: Fehler: Neuzuweisung zu val updateCount = updateCount + 1 kommt aus der Inc-Methode. – Trenton

Antwort

7

Sie brauchen nicht die var in der Unterklasse Konstruktor Unterschrift zu erklären:

class B (val name: String, /* note no var */ updateCount: Int) extends A(updateCount) { 
    //... 
} 

Dies auch mit val s in ihren Konstruktoren Klassen erstreckt sich auch:

scala> class C(val i: Int) 
defined class C 

scala> class D(j: Int) extends C(j) 
defined class D 
+0

Dies funktioniert nicht. Wenn ich das genaue Beispiel verwende ich zur Verfügung gestellt, die var von update entfernen, erhalte ich (Fragment von extend.scala): 7: Fehler: Neuzuordnung val update = update + 1 aus der inc Methode kommen. – Trenton

+0

Sie müssen nur die Parameter in Klasse B umbenennen: Verwenden Sie 'updateCountIn' in der Konstruktorsignatur und rufen Sie den Konstruktor der Klasse A auf; Sie können immer noch auf 'updateCount' im Konstruktor/Körper der Klasse B zugreifen. – bbarker

4

Sie müssen vermeiden Der Bezeichner wurde für B deklariert, wobei der für A deklarierte Bezeichner schattiert wird. Der einfachste Weg ist, einen anderen Namen zu wählen. Wenn aber wirklich Sie, wirklich nicht das tun wollen, hier ist eine Alternative:

class B (val name: String, updateCount: Int) extends A(updateCount) { 
    self: A => 
    def inc(): Unit = { 
    self.updateCount = self.updateCount + 1 
    } 
} 

Und, nebenbei bemerkt, fallen die var von B Erklärung.

+1

Wow, das ist ziemlich umständlich.Dies scheint eine seltsame Einschränkung der Sprache zu sein. Wenn ich einen Vererbungsgraphen 5 tief hätte, müsste ich weiterhin mit "falschen" Namen für diese Argumente kommen? updateCountDontUse1 und in seiner Unterklasse updateCountDontUse2 usw.? Es ist nicht nur der Name ... es ist auch der Craft. Es ist ein zusätzliches Feld, das in meiner Klasse sitzt und jemanden bittet, es zu benutzen und schlechte Ergebnisse zu bekommen. – Trenton

+2

Das ist die Sache ... die Parameter für die Klasse sind nicht wirklich Felder, es sei denn, mit 'val' oder' var' vorangestellt. Wenn Sie sie nirgendwo außer dem Konstruktor verwenden, werden sie nicht als Felder in der Klasse gespeichert. –

2

Wenn Sie das Schlüsselwort var in den Parametern verwenden, wird der übergebene Wert ein neuer var in der Klasse sein. Wenn Sie das nicht tun, wird es (nur) zum Konstruktorparameter, und Sie verwenden den Wert für var, indem Sie ihn an den Konstruktor übergeben. Also das Beispiel, das Leute gegeben haben

ist richtig.

Allerdings macht scala Konstruktor Parameter direkt verfügbar für die Methoden in der Klasse (ich bin mir nicht sicher warum), wenn Sie also den gleichen Namen verwenden, werden Sie feststellen, dass Ihr Code mit dem Fehler reassignment to val kompiliert die "var" neu zuweisen. Im folgenden Codefragment schattiert beispielsweise der unveränderliche Konstruktorparameter die vererbte var und kann daher nicht dem Parameter zugewiesen werden.

+0

Klasse B (Wertname: String, updateCount: Int) erweitert A (updateCount) wird nicht für mich kompilieren. Ich bekomme (Fragment von extend.scala): 7: Fehler: Neuzuweisung zu val updateCount = updateCount + 1 – Trenton

+0

Die erste Version kompiliert. Die zweite Version tut absichtlich nicht, und demonstriert das Problem mit der Verwendung des gleichen Namens für die Variable und den Konstruktorparameter. –

0

Wie andere erwähnen, überschattet Ihr Konstruktor param in B die Version der Superklasse. Hier ist der Code, der funktioniert und keinen Selbsttest erfordert:

Verwandte Themen