2017-02-14 5 views
0

私は、俳優のreceiveメソッドのようなタイプを消去するインターフェイスを通して関数を渡す必要があります。だから私は消去された型パラメータを格納し、引数をキャストするために使用したいと思います。関数の型を削除するときの関数の使い方は?

val c0 = a0.action(source) 
val c1 = a1.action(c0) 

明らかに失敗します:

class Store[R,T](val action : R => T)(implicit i : TypeTag[R], o : TypeTag[T]) { 
    val in : Type = i.tpe 
    val out : Type = o.tpe 
} 
object Store { 
    type Any = Store[_,_] 
    def apply[R,T](action : R => T)(implicit i : TypeTag[R], o : TypeTag[T]) : Store[R,T] = new Store(action) 
} 

final case class Box[T](unbox : T) 

def getType[T](x : T)(implicit t : TypeTag[T]) : Type = t.tpe 

val source = Box("test") 

val x = Store[Box[String], Box[Int]](s => Box(s.unbox.length)) 
val y = Store[Box[Int], Box[Boolean]](i => Box(i.unbox % 3 == 0)) 

val all : List[Store.Any] = List(x,y) 
val a0 = all(0) 
val a1 = all(1) 

私はそのようなチェーン保存されたアクションをしたい

私はすべての種類は、実行時に一致していることを確認できた
error: type mismatch; 
found : source.type (with underlying type Box[String]) 
required: _$1 
    val c0 = a0.action(source) 
        ^
one error found 

assert(getType(source) <:< a0.in) 
assert(a0.out <:< a1.in) 

しかし、どうすれば実際の引数を適切な型に変換しますか? asInstanceOfには実行時のリフレクションではなく、コンパイル時の型が必要です。他にどんなトリックがありますか?それを行うには

答えて

1

一つの方法は、ClassTag[T]とそのunapplyメソッドを使用することです:あなたはSome[T]値を受け取るTobjectのタイプがある

def castIfPossible[T](object: Any)(implicit tag: ClassTag[T]): Option[T] = 
    tag.unapply(object) 

場合は、そうでなければ、Noneを受け取るでしょう。

あなたのコードで行う必要があることは、タイプが常に一致していることを前提とすることです(しかし、おそらくリフレクションは必要ありません)。またはmapまたはflatMapを組み合わせて値を組み合わせます。

個人的には、Tがパラメータ化されているかのように、反射が全くないかどうかを判断しようとします。次に、問題を扱うために型クラスのようなものを使用します。しかし、私はそれが常に可能ではないかもしれないことを理解します。

+0

'ClassTag [T]'は、 'T'型を保つ必要があります。 >型が常に< - それは問題ではないと仮定するか、上に示したように常に型を宣言できます。 >型のクラス<しかし、すべての型が失われたときに実行時には役に立たない。 'Any'型を受け入れるインタフェースにオブジェクトを渡す必要がある場合は、ランタイムパターンのマッチングだけが可能です。 – ayvango

+0

ある時点で、あなたは' T 'の型を知っています - これは 'ClassTag'とオブジェクトにアクセスする前にオブジェクトを実際に制御できない場合や、型がすでに失われている場合を除き、それを忘れるコード部分に渡してください。 タイプ「T」を保持するために、必ずしも必要ではありません。ある時点で、存在するタイプの使用を開始するかもしれません。それで、Tは 'SomeTHandler [T](値:T)(暗黙のタグ:ClassTag [T])'クラスの内部で知ることができますが、インターフェースレベルでは 'SomeHanlderT [_]'と呼ばれます。 –

+0

そして、タイプがすでに消去されているときに 'SomeHandlerT [_]'が 'Option [T]'を返すとはどうでしょうか? – ayvango

関連する問題