将Scala类型重用为方法定义中的边界

时间:2013-03-21 15:30:22

标签: scala generics types existential-type type-bounds

是否可以编写类似的东西并重用HelperTest.AnyHelper类型?

class HelperUtil 
{    
/* this is what I would like to write... reuse the AnyHelper type in the definition */
   def accept[HelperTest.AnyHelper](helper : HelperTest.AnyHelper) = 
   {
       // code here
   }
}

object HelperTest 
{
    type AnyHelper = T forSome { type T <: GenericHelper }
}

abstract class GenericHelper 
{
    val name = ""
}

目前我被迫写这个,因为编译器不会让我:

class HelperUtil 
{
/* gets too verbose, if the generic type gets more complex and would be useful to reuse the type */
    def accept[T <: GenericHelper](helper : T) = 
    {
        // code here
    }
}

abstract class GenericHelper 
{
    val name = ""
}

或者我完全走错了路?

1 个答案:

答案 0 :(得分:1)

我猜你错误地认为签名中的类型参数如def accept[T]如何工作。此签名中的类型变量T获取绑定,即T作为新类型变量引入。如果在当前上下文中已存在具有相同名称的类型变量,则它将被新绑定的T遮蔽。考虑这个例子:

class Foo[T] {
  def id[T](t: T) = t
}

类签名绑定一个可以在类体中引用的新T。但是,方法签名也会绑定T,这会影响类T。结果是,您可以使用某种类型T实例化类X,使用其他类型T实例化方法Y

val f = new Foo[String]
f.id(0)

返回您的代码。你的签名

def accept[HelperTest.AnyHelper](helper : HelperTest.AnyHelper)

因此尝试绑定编译器拒绝的新类型变量HelperTest.AnyHelper,因为类型变量可能不包含点(.)。

请执行以下操作:

import scala.language.existentials

trait A
class B1 extends A
class C1 extends B1
class B2 extends A

object HelperUtil {
  type MyA = T forSome { type T <: A }
}

class HelperUtil {
   /* Reuse type declaration */
   def foo(a: HelperUtil.MyA) = println(a.getClass.getName)
   def bar(a: HelperUtil.MyA) = println(a.getClass.getName)
   def baz(a: HelperUtil.MyA) = println(a.getClass.getName)
}

val hu = new HelperUtil

/* Instantiate with different types */
hu.foo(new B1) // B1
hu.foo(new B2) // B2
hu.bar(new C1) // C1