开发者

What's the Scala for a declaration of "Class<? extends SomeType>"

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:

  1. Existential types produce the same bytecode as Java wildcards (and their major intended use is interoperation with wildcards).

  2. 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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜