2017-08-24 90 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