2016-05-18 18 views
2

背景Scalaでランタイム型パラメータを持つジェネリックメソッドを呼び出すにはどうすればよいですか?

私はAkkaのストリームを使用していると私はOutSeqときのために特別であるFlow[In, Out, Mat]にいくつかの拡張メソッドを追加したいです。 (後でフォローする詳細)次に

trait StageOps[+Out, +Mat] { 
    protected val stage: FlowOps[Out, Mat] 
    type Repr[+O] = stage.Repr[O] 
    type Closed = stage.Closed 
} 

私はこれを持っている:

trait FramingOps[Out <: Seq[_], Mat] extends StageOps[Out, Mat] { 
    def frame(start: Out, end: Out): Repr[Out] = { 
    ... 
    } 
} 

そして今、私はこの特性を始めています

は、タイプフィールドで取得することを容易にします暗黙的な変換:

implicit class SeqFlowOps[In, Out <: Seq[_], Mat](val stage: Flow[In, Out, Mat]) 
    extends FramingOps[Out, Mat] {} 

これは素晴らしい仕事をし、私はのような何かを行うことができます:

val byteFlow: Flow[ByteString, ByteString, _] = ??? // Some flow from somewhere else 
byteFlow.frame(ByteString(0x0B), ByteString(0x1C, 0x0D)) // Implicit conversion 

問題

私はこのような何かする必要がある場所FramingOps#frameの実装が発展してきました。今のvar buffer = Seq.empty[Any]を使用する必要が

def frame(start: Out, end: Out): Repr[Out] = { 
    val maxBufferSize = math.max(start.length, end.length) - 1 
    val checkForMalformedChunk = stage.statefulMapConcat[Out](() => { 
    var buffer = Seq.empty[Any] 
    (chunk: Out) => { 
     buffer = buffer ++ chunk 
     if (buffer.containsSlice(start) || buffer.containsSlice(end)) ??? // Bad encoding! 
     buffer = buffer.takeRight(maxBufferSize) 
     immutable.Seq(chunk) 
    } 
    }) 
    checkForMalformedChunk.prepend(Source.single(start)).concat(Source.single(end)) 
} 

はOKですが、私は確信しているIより良いことができます。私ができるようになりました

abstract class FramingOps[Out <: Seq[_] : TypeTag, Mat] extends StageOps[Out, Mat] { ... } 

trait FramingOps[Elem, Out <: Seq[Elem], Mat] extends StageOps[Out, Mat] { ... } 

は、だから私は TypeTagはおそらく唯一のオプションです使用して考え出し:要素の型を提供する方法がないよう

この試みは、暗黙的な変換を破ります実行時に要素タイプを取得するには:

implicitly[TypeTag[Out]] match { case TypeRef(_, _, List(elemType)) => elemType } 

これは、正しいタイプの空のシーケンスを作成するためですか?リフレクションを使用し続け、タイプパラメータmyslefを指定する必要がありますか?もしそうなら、どうしたらいいですか?

答えて

0

Elem型にアクセスするには、次のいずれかの方法で暗黙のクラスを定義できませんか?

implicit class SeqFlowOps[In, Out[X] <: Seq[X], Mat, Elem](val stage: Flow[In, Out[Elem], Mat]) 
    extends FramingOps[Elem, Out[Elem], Mat] {} 

または

implicit class SeqFlowOps[In, Out, Mat, Elem](val stage: Flow[In, Out with Seq[Elem], Mat]) 
    extends FramingOps[Elem, Out, Mat] {} 
私は徹底的にこれをテストしていません

...私は実際にこれをまだ試してみる機会がなかったが、私はかなり確信している

+0

その最初のもの私がすでに試みたものです。暗黙の変換が失敗しました。私はどこかの型パラメータを見逃しているのだろうかと思っています。コンパイラがその方法を知るための十分な情報があるはずです。私は 'Out'がもう' Seq'ではないので、2番目のオプションはうまくいかないと思います。 – Steiny

+0

私はAkka Streamsを使用していないので、少し単純なバージョンで両方を試しましたが、彼らは基本的なREPLセッションで働いていました。 –

関連する問題