2016-11-29 3 views
2

ich die folgende Klassendefinition für eine veränderbare Array in Scala haben „Wert kein Mitglied ist“:@specialized Tag hinzufügen, verursacht Fehler in Scala

class ResizeableArray[T: Manifest](initialCapacity: Int) { 
    private var capacity = initialCapacity 
    private var arr = Array.ofDim[T](capacity) 
} 

Diese Definition funktioniert gut, aber wenn ich @specialized(Int) fügen sich zu spezialisieren für primitive Art Int, ich folgende seltsame Fehlermeldung erhalten:

class ResizeableArray[@specialized(Int) T: Manifest](initialCapacity: Int) { 
    private var capacity = initialCapacity 
    private var arr = Array.ofDim[T](capacity) 
} 

<console>:15: error: value capacity is not a member of ResizeableArray$mcI$sp 
     private var arr = Array.ofDim[T](capacity) 

Kann mir jemand erklären, was hier los? Ich benutze Scala 2.12.

Antwort

4

@specialized Nach dem Specialized SID Section 3.1:

Not all members of a class are specialized. Currently, specialized variants of a member m are created only when m’s type contains at least one specialized naked type parameter, or an array of a naked specialized type parameter.

Normalerweise dies keinen Unterschied machen könnte, aber es funktioniert hier. Dies liegt daran, wenn Sie ResizeableArray für Int spezialisieren, der Compiler eine andere Klasse wie folgt erzeugt (beachten Sie, dass var capacity nicht da ist):

<specialized> class ResizeableArray$mcI$sp extends ResizeableArray { 
    implicit <paramaccessor> private val evidence$1: scala.reflect.Manifest = _; 
    <specialized> protected[this] var arr$mcI$sp: Array[Int] = _; 
    <accessor> <specialized> protected def arr$mcI$sp(): Array[Int] = ResizeableArray$mcI$sp.this.arr$mcI$sp; 
    override <accessor> <specialized> protected def arr(): Array[Int] = ResizeableArray$mcI$sp.this.arr$mcI$sp(); 
    <accessor> <specialized> protected def arr$mcI$sp_=(x$1: Array[Int]): Unit = ResizeableArray$mcI$sp.this.arr$mcI$sp = x$1; 
    override <accessor> <specialized> protected def arr_=(x$1: Array[Int]): Unit = ResizeableArray$mcI$sp.this.arr$mcI$sp_=(x$1); 
    def specInstance$(): Boolean = true; 
    override <bridge> <specialized> <artifact> protected def arr_=(x$1: Object): Unit = ResizeableArray$mcI$sp.this.arr_=(x$1.$asInstanceOf[Array[Int]]()); 
    override <bridge> <specialized> <artifact> protected def arr(): Object = ResizeableArray$mcI$sp.this.arr(); 
    <specialized> def <init>(initialCapacity: Int, evidence$1: scala.reflect.Manifest): ResizeableArray$mcI$sp = { 
     ResizeableArray$mcI$sp.this.evidence$1 = evidence$1; 
     ResizeableArray$mcI$sp.super.<init>(initialCapacity, evidence$1); 
     ResizeableArray$mcI$sp.this.arr$mcI$sp = scala.Array.ofDim(ResizeableArray$mcI$sp.this.initialCapacity(), evidence$1).$asInstanceOf[Array[Int]](); 
    () 
    } 
    } 

Durch die obige Definition nur die Mitglieder, die den speziellen Parameter in irgendeiner Weise enthalten in der Implementierung von ResizeableArray$mcI$sp übersteuert werden. Das bedeutet, dass capacity in der spezialisierten Klasse nicht überschrieben oder implementiert wird. Daher erwartet der Compiler, dass er stattdessen bei Bedarf vererbt wird. Leider ist capacity privat, es wird nicht vererbt und Sie erhalten einen Compilerfehler. Ich weiß nicht, ob private Mitglieder hier übersehen oder bewusst ausgeschlossen wurden, aber Sie müssen vorsichtig sein, wenn Sie sie in speziellen Klassen verwenden.

In diesem Fall ist eine einfache Behelfslösung tun:

class ResizeableArray[@specialized(Int) T: Manifest](initialCapacity: Int) { 
    private var capacity = initialCapacity 
    private var arr = Array.ofDim[T](initialCapacity) 
} 

Der einzige andere Weg, um dies wäre capacity öffentlich zu machen, was sicherlich würden Sie hier nicht wollen, aber in akzeptabel sein kann andere Fälle (wenn es nicht veränderbar ist).

0

Wenn Sie eine generische Klasse erstellen und die @ specialized-Annotation verwenden, generiert der Compiler tatsächlich zwei Versionen der Klasse: die normale generische Klasse, in der der type-Parameter gelöscht wird, und eine spezielle Unterklasse. In Ihrem Fall passiert das Problem nur in $mcI$sp Methode der Scala spezifischen Klasse. Ich habe es gerade versucht, indem ich privat entfernte und der Fehler verschwand.

class ResizeableArray[@specialized(Int) T: Manifest](initialCapacity: Int) { 
var capacity = initialCapacity 
    private var arr = Array.ofDim[T](capacity) 
} 

Ich bin nicht sehr sicher, dieses Problem ist mit variablem Umfang.

Hinweis Array ist nicht

+0

Ich bemerkte auch, dass durch Entfernen von privat verschwindet die Fehlermeldung, aber kann nicht herausfinden, warum. Sie sagen, dass Array nicht spezialisiert ist, Sie meinen, dass ich für die primitive Variante nicht das Java-Äquivalent von int [Kapazität] bekomme und es immer noch Objekt [Kapazität] sein wird? – Wickoo

Verwandte Themen