sca*_*out 34 generics scala type-parameter
例:
import scala.actors._
import Actor._
class BalanceActor[T <: Actor] extends Actor {
val workers: Int = 10
private lazy val actors = new Array[T](workers)
override def start() = {
for (i <- 0 to (workers - 1)) {
// error below: classtype required but T found
actors(i) = new T
actors(i).start
}
super.start()
}
// error below: method mailboxSize cannot be accessed in T
def workerMailboxSizes: List[Int] = (actors map (_.mailboxSize)).toList
.
.
.
Run Code Online (Sandbox Code Playgroud)
注意第二个错误表明它知道actor项是"T",但不是"T"是actor的子类,而是在类通用定义中受到约束.
如何纠正此代码(使用Scala 2.8)?
oxb*_*kes 25
编辑 - 道歉,我只是注意到你的第一个错误.没有办法T
在运行时实例化,因为编译程序时类型信息会丢失(通过类型擦除)
您将不得不通过一些工厂来实现建设:
class BalanceActor[T <: Actor](val fac: () => T) extends Actor {
val workers: Int = 10
private lazy val actors = new Array[T](workers)
override def start() = {
for (i <- 0 to (workers - 1)) {
actors(i) = fac() //use the factory method to instantiate a T
actors(i).start
}
super.start()
}
}
Run Code Online (Sandbox Code Playgroud)
这可能与某些演员一起使用CalcActor
如下:
val ba = new BalanceActor[CalcActor]( { () => new CalcActor } )
ba.start
Run Code Online (Sandbox Code Playgroud)
暂且不说:您可以使用until
而不是to
:
val size = 10
0 until size //is equivalent to:
0 to (size -1)
Run Code Online (Sandbox Code Playgroud)
Wal*_*ang 15
使用清单:
class Foo[A](a: A)(implicit m: scala.reflect.Manifest[A]) {
def create: A = m.erasure.newInstance.asInstanceOf[A]
}
class Bar
var bar1 = new Bar // prints "bar1: Bar = Bar@321ea24" in console
val foo = new Foo[Bar](bar1)
val bar2 = foo.create // prints "bar2: Bar = Bar@6ef7cbcc" in console
bar2.isInstanceOf[Bar] // prints "Boolean = true" in console
Run Code Online (Sandbox Code Playgroud)
显然,Manifest在2.7.X中没有记录,所以要小心使用它.相同的代码也在每晚2.8.0中运行.
Jos*_*osh 13
现在有一个正确而安全的方法.Scala 2.10引入了TypeTags,它实际上使我们能够在使用泛型类型时克服擦除问题.
现在可以按如下方式对您的类进行参数化:
class BalanceActor[T <: Actor :ClassTag](fac: () => T) extends Actor {
val actors = Array.fill[T](10)(fac())
}
Run Code Online (Sandbox Code Playgroud)
通过这样做,我们要求在实例化类时可以使用隐式ClassTag [T].编译器将确保这种情况并生成将ClassTag [T]传递给类构造函数的代码.ClassTag [T]将包含有关T的所有类型信息,因此,编译时编译时可用的相同信息(预擦除)现在也可以在运行时使用,使我们能够构建一个数组[T].
请注意,仍然无法做到:
class BalanceActor[T <: Actor :ClassTag] extends Actor {
val actors = Array.fill[T](10)(new T())
}
Run Code Online (Sandbox Code Playgroud)
这不起作用的原因是编译器无法知道类T是否具有无参数构造函数.
归档时间: |
|
查看次数: |
20263 次 |
最近记录: |