我有一个函数,它接受的类型参数T
必须是this.type
的子类型:
def injectFrom[T <: this.type](same: T): Unit = ...
然而每次我使用它时,编译器都给了我一个
类型T无法推断“错误
每次都可以通过明确指定T
(instance_variable).type
来解决问题。我怎么能避免将来这样做?
答案 0 :(得分:3)
this.type
是一种单独的对象或类实例,而不是类。
在以下代码a1
和a2
中将有不同的this.type
:
class A
val a1 = new A()
val a2 = new A()
因此,类型参数[T <: this.type]
并不真正有意义,因为您无法extend
object
或实例。
如果你想要一个设计,那么子类中的函数只能接受那个子类的实例(以及因此只接受那个子类的子类的实例),你必须使用type参数或类型变量使类型显式化:
trait A {
type Self
def injectFrom(same: Self): Unit = ???
}
class B extends A {
type Self = B
}
class C extends A {
type Self = C
}
或Scala在Ordered
实现中所做的事情:
trait A[Self] {
def injectFrom(same: Self): Unit = ???
}
class B extends A[B]
class C extends A[C]
在这两种情况下,new B().injectFrom(new B())
都会编译,但new B().injectFrom(new C())
不会。
第二个示例的修改,允许您在this injectFrom this
内A
:
trait A[Self] {
def injectFrom(same: A[Self]): Unit = ???
def test() {
this injectFrom this
}
}
答案 1 :(得分:0)
编译器坚决拒绝推断单例类型。
scala> class C { def f[A <: this.type](a: A) = ??? }
defined class C
scala> val c = new C
c: C = C@71f2a7d5
scala> c f c
<console>:10: error: inferred type arguments [C] do not conform to method f's type parameter bounds [A <: c.type]
c f c
^
<console>:10: error: type mismatch;
found : C
required: A
c f c
^
经典参考:
http://www.artima.com/pins1ed/modular-programming-using-objects.html#i-108236764-1
通常这些类型太具体而无用,这就是为什么 编译器不愿意自动插入它们。
答案 2 :(得分:0)
这样做你想要的吗?我不知道这是不是最好的方式,但是......
trait Foo {
class Tag[U <: AnyRef](x: U) {
type UT = U
}
val tag = new Tag(this)
def injectFrom[T <: tag.UT](same: T): Unit = {
println("Injected")
()
}
}
class NotBar
{
}
class Bar extends Foo
{
injectFrom(this)
val notThis = new NotBar
injectFrom(notThis)
}
结果:
x.scala:20: error: inferred type arguments [NotBar] do not conform to method injectFrom's type parameter bounds [T <: Bar.this.tag.UT]
injectFrom(notThis)
^
x.scala:20: error: type mismatch;
found : NotBar
required: T
injectFrom(notThis)
^
two errors found
编辑:这可能不是你想要的,因为这将允许注入这个类的任何子类型,而不是从实例的特定子类型注入?