I'm obviously 开发者_Go百科missing something about why the following does not compile:
trait SomeTrait{
def homepageClass[A <: SomeType]: Class[A]
}
class SomeOtherType extends SomeType
object SomeObject extends SomeTrait{
def homepageClass = classOf[SomeOtherType]
}
The problem here is that the following two declarations are different:
def homepageClass[A <: SomeType]: Class[A] // has type parameters
def homepageClass = classOf[SomeOtherType] // doesn't have type parameters
To accomplish what you want you need to declare an abstract type, like this:
trait SomeTrait{
type A <: SomeType
def homepageClass: Class[A]
}
object SomeObject extends SomeTrait {
type A = SomeOtherType
def homepageClass: Class[A] = classOf[SomeOtherType]
}
Or
trait SomeTrait[A <: SomeType] {
def homepageClass: Class[A]
}
object SomeObject extends SomeTrait[SomeOtherType] {
def homepageClass: Class[SomeOtherType] = classOf[SomeOtherType]
}
def homepageClass[A <: SomeType]: Class[A]
says "whatever subclass A
of SomeType
you give, I can return a Class[A]
. In particular, it can be called like this:
class SomeThirdType extends SomeType
val x: Class[SomeThirdType] = SomeObject.homepageClass[SomeThirdType]
A more direct equivalent than Daniel gives is an existential type:
trait SomeTrait{
def homepageClass: Class[A forSome {type A <: SomeType}]
}
or
trait SomeTrait{
def homepageClass: Class[_ <: SomeType]
}
UPDATE: Two differences between solutions I can think about:
Existential types produce the same bytecode as Java wildcards (and their major intended use is interoperation with wildcards).
You can write a refinement type for the abstract type member solution:
val x: SomeTrait {type A = SomeOtherType} = SomeObject
I don't think you can for existential types.
Any others?
精彩评论