2017-08-24 130 views
0
class Foo { 
    def copy: this.type = new Foo().asInstanceOf[this.type] 
    def multiply(n: Int): Seq[this.type] = (0 until n).map(_ => copy) 
} 

此代码失败,就像一个错误编译:`this.type`:为什么不编译?

<console>:33: error: type mismatch; 
found : scala.collection.immutable.IndexedSeq[Foo] 
required: Seq[Foo.this.type] 

我想不出的解释是:copy回报this.typemultiply只是调用.copy ......为什么结果不兼容?

这是一个编译器错误,或者是有我缺少为什么这不应该工作的实际原因是什么?

回答

0

这是一个错误或JVM限制。要使其工作,请在Foo中为this.type创建一个类型别名,或者明确指定map的类型参数。

不过,我不认为有是必要的运行时强制转换为this.type的使用情况。无论您使用什么样的应用,都应该有一种更好的方法。

+0

我同意演员似乎是一个非常糟糕的主意。此外,编译器不会在没有约束的情况下推断单例类型。例如,“身份(foo)”不是'foo.type',除非是'object foo'。 –

+1

其实'身份(富):foo.type'而不是'标识(名单(富).MAP(_ =>富)):列表[foo.type]'所以它是因为'CanBuildFrom'推断。 –

0

这只是类型推断不会推断单身。这不是一个错误,而是一个有意识的语言设计决策。你需要给明确的参数map

(0 to n).map[this.type, Seq[this.type]] { _ => copy } 

如果你需要的话,你可以使用Singleton类型势必创建推断单类型的方法:

def replaceAll[In, Elem <: Singleton, Out](coll: FilterMonadic[_, In])(e: Elem)(implicit cbf: CanBuildFrom[In, Elem, Out]): Out 
= coll.map { _ => e } 

用法:

replaceAll(0 to n)(x: x.type) // Won't work without ascription, but cleaner than above 

另外,请不要使用asInstanceOf[this.type]。单身人士类型基于参考平等,而不是equals。因此,你得到的东西,如:

val foo = new Foo 
val foo2: foo.type = foo.copy 
foo2.isInstanceOf[foo.type] // false because foo2 neq foo 

您可能希望F-bounds,来代替。

+0

但看到我对其他答案的评论。 –

+0

等等...你不是说'def copy:this.type = clone()。asInstanceOf [this.type]'应该不起作用,是吗?因为它在为我工作...... – Dima

+0

我的意思是'isInstanceOf'停止工作。 'asInstanceOf'可以正常工作,但不应该以这种方式使用,因为它会中断'isInstanceOf'。 – HTNW