2

このようなものを記述して 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 = ""
}

それとも、私は完全に間違った方向に進んでいますか?

4

1 に答える 1

1

などの署名の型パラメーターがどのように機能するかについて、あなたは間違っていると思いますdef accept[T]Tこの署名の型変数はバインドされます。つまりT、新しい型変数として導入されます。現在のコンテキストに同じ名前の型変数が既に存在する場合、新しくバインドされた によってシャドウされTます。次の例を検討してください。

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

Tクラス シグネチャは、クラス本体で参照できるnew をバインドします。ただし、メソッド シグネチャは aTもバインドし、クラスをシャドウしTます。その結果、あるT型でクラスをインスタンス化し、他の型Xでメソッドをインスタンス化できます。TY

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
于 2013-03-21T15:55:36.037 に答える