2016-11-29 25 views
2

錯誤我對Scala中的一個可調整大小的數組下面的類定義:添加@specialized標記導致「價值不是其成員」在斯卡拉

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

這個定義工作正常,但是當我添加@specialized(Int)專攻對於基本類型Int,我得到以下奇怪的錯誤:

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) 

有人能向我解釋這是怎麼回事呢?我正在使用Scala 2.12。

回答

4

按照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.

通常情況下,這可能不會有所作爲,但它確實在這裏。這是因爲當你專注ResizeableArrayInt,編譯器生成這樣的另一個類(注意:var capacity是不存在的):

<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]](); 
    () 
    } 
    } 

通過上面的定義,只包含了專門的參數以某種方式成員在執行ResizeableArray$mcI$sp時被覆蓋。這意味着capacity不會被覆蓋或在專門的類中實現,所以編譯器希望它會被繼承,如果需要的話。不幸的是,由於capacity是私有的,因此它不會被繼承,並且會出現編譯器錯誤。我不知道私人會員在這裏是被忽視還是被有意識地排除在外,但是在專門的課程中使用它們時需要小心。

在這種情況下,一個簡單的工作,周圍的人也會做:

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

解決這個問題的唯一的其他方式將是使capacity公開的,這你一定不希望在這裏,但可能是在可以接受的其他情況下(當它不可變時)。

0

如果您創建一個泛型類並使用@specialized註釋,那麼編譯器實際上會生成該類的兩個版本:正常泛型,其中類型參數被擦除,以及一個特殊的子類。在你的情況下,問題只發生在Scala特定類的$mcI$sp方法中。我只是通過刪除私人內容來嘗試它,錯誤消失了。

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

我不是很確定,這個問題是可變範圍。

注意數組不@specialized

+0

我也注意到,通過刪除私人,錯誤消息消失,但無法弄清楚爲什麼。你說這個數組沒有專門化,你的意思是說,對於原始變體,我沒有得到Java [等於]的等價物,它仍然是Object [capacity]? – Wickoo

相關問題