我写了几个看起来像这样的函数:
def myWrite(os: OutputStream) = {}
def myWrite(w: Writer) = {}
现在两者非常相似,我想我会尝试编写函数的单个参数化版本。
我开始使用Java OutputStream和Writer中常见的两种方法的类型:
type Writable[T] = {
def close() : Unit
def write(cbuf: Array[T], off: Int, len: Int): Unit
}
一个问题是OutputStream写入Byte
而Writer写入Char
,因此我使用T
对类型进行了参数化。
然后我写了我的功能:
def myWrite[T, A[T] <: Writable[T]](out: A[T]) = {}
并尝试使用它:
val w = new java.io.StringWriter()
myWrite(w)
结果:
<console>:9: error: type mismatch;
found : java.io.StringWriter
required: ?A[ ?T ]
Note that implicit conversions are not applicable because they are ambiguous:
both method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
and method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
are possible conversion functions from java.io.StringWriter to ?A[ ?T ]
myWrite(w)
我尝试了其他一些类型和参数的组合,到目前为止无济于事。
我的问题是,是否有办法实现这一点,如果有的话,如何实现。
(请注意,myWrite的实现在内部需要知道参数化write()方法的类型T
,因为它需要像在新的ArrayT中一样创建缓冲区。)
更新:“正确”解决方案不起作用,因为编译器中存在错误:https://lampsvn.epfl.ch/trac/scala/ticket/2672
答案 0 :(得分:1)
首先,您无需在A
中参数化myWrite
。您的目标类不是通用的!其次,您不需要明确允许子类 - 只需让继承为您做到这一点。
def myWrite[T](out: Writable[T]) = {}
现在该方法可以推断出类型T
。只要您因某些原因不需要A
的真实类型,这对您有用:
myWrite(new StringWriter)
但是,你会遇到一个问题:
def myWrite[T](out: Writable[T]) = new Array[T](0) // Doesn't work!
问题是这是通用代码。它不知道T
是什么 - 它可能是任何东西!因此,您需要告诉编译器传递标识T
的信息:
def myWrite[T : ClassManifest](out: Writable[T]) = new Array[T](0)
(编辑:简化了答案,使其真正有效。)
(编辑:实际上,它不太有效 - 请参阅评论。)
答案 1 :(得分:0)
这有效:
myWrite(w.asInstanceOf[Writable[Char]])
...所以你会认为这会奏效:
implicit def wrToWr(w:java.io.Writer): Writable[Char] = w.asInstanceOf[Writable[Char]]
......但事实并非如此。我不知道为什么不:
scala> myWrite(w)
<console>:17: error: type mismatch;
found : java.io.StringWriter
required: Nothing
myWrite(w)
^
什么都没有来自?