背景Scalaでランタイム型パラメータを持つジェネリックメソッドを呼び出すにはどうすればよいですか?
私はAkkaのストリームを使用していると私はOut
がSeq
ときのために特別である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を指定する必要がありますか?もしそうなら、どうしたらいいですか?
その最初のもの私がすでに試みたものです。暗黙の変換が失敗しました。私はどこかの型パラメータを見逃しているのだろうかと思っています。コンパイラがその方法を知るための十分な情報があるはずです。私は 'Out'がもう' Seq'ではないので、2番目のオプションはうまくいかないと思います。 – Steiny
私はAkka Streamsを使用していないので、少し単純なバージョンで両方を試しましたが、彼らは基本的なREPLセッションで働いていました。 –