简体   繁体   English

重用Scala类型作为方法定义中的界限

[英]Reuse Scala type as bounds in method definition

Is it possible to write something like this and reuse the HelperTest.AnyHelper type? 是否可以编写这样的东西并重用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 = ""
}

Currently I am forced to write this, since the compiler won't let me: 目前,由于编译器不允许我这样做,我不得不这样做:

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 = ""
}

Or am I completely on the wrong track? 还是我完全走错了路?

I guess you are mistaken about how type parameters in a signature such as def accept[T] work. 我想您对def accept[T]类的签名中的类型参数如何工作感到误解。 The type variable T in this signature gets bound , that is, T is introduced as a new type variable. 此签名中的类型变量T受到限制 ,即T被引入为新的类型变量。 If there already exists a type variable with the same name in the current context, then it will be shadowed by the newly bound T . 如果在当前上下文中已经存在一个具有相同名称的类型变量,那么它将被新绑定的T遮盖。 Consider this example: 考虑以下示例:

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

The class signature binds a new T that can be referred to in the class body. 类签名绑定了可以在类主体中引用的新T However, the method signature binds a T as well, which shadows the class T . 但是,方法签名也绑定了一个T ,从而遮盖了类T With the result, that you can instantiate the class T with some type X and the method T with some other type Y : 结果是,您可以使用某种类型X实例化类T以及使用其他类型Y实例化方法T

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

Back to your code. 回到您的代码。 Your signature 你的签名

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

thus tries to bind a new type variable HelperTest.AnyHelper - which the compiler rejects, because type variables may not contain a dot ( . ). 因此尝试绑定一个新的类型变量HelperTest.AnyHelper编译器拒绝,因为类型变量可能不包含点( . )。

Do the following instead: 而是执行以下操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM