2016-11-29 77 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