2017-03-15 36 views
0

我想發佈一個How to use Scala's this typing, abstract types, etc. to implement a Self type? 的答案的後續行動,但由於我沒有足夠的信譽來發布後續行動,所以我無法做到這一點。斯卡拉返回自我參數化功能

我有一個抽象類,並希望在一個函數,以便能夠在其他參數化的功能,使用該功能返回的具體類型的實例:

trait Abstract { 
    def test(): <concrete type> 
} 

class Concrete extends Abstract { 
    override def test(): Concrete = new Concrete 
} 

def fun[C <: Abstract](c: C): C = c.test() 

this.type第一個解決方案不爲我工作,因爲我想能夠在test()方法中返回Concrete的新實例。

所以,我想第二個解決方案:

trait Abstract { 
    type Self <: Abstract 
    def test(): Self 
} 

class Concrete extends Abstract { 
    override type Self = Concrete 
    override def test(): Concrete = new Concrete 
} 

,但它不會編譯:

def fun[C <: Abstract](c: C): C = c.test() 

> [error] type mismatch; 
> [error] found : c.Self 
> [error] required: C 

這是非常合乎邏輯的,因爲我可以在另一種具體實現Abstract已覆蓋Self類型有什麼。

我想什麼來避免的是:

trait Abstract2[C] { 
    def test(): C 
} 

class Concrete2 extends Abstract2[Concrete2] { 
    override def test(): Concrete2 = new Concrete2 
} 

def fun2[C <: Abstract2[C]](c: C): C = c.test() 

,因爲它是很難供客戶端使用。還有其他的可能嗎?

回答

0

你想要的簽名是錯誤的,因爲它允許以下代碼:

val c1: Concrete = new Concrete 
val c2: c1.type = fun[c1.type](c1) 

fun(c1)返回的值是不是c1,因此不具有類型c1.type

但您可以將其更改爲def fun[C <: Abstract](c: C): c.Self = c.test()。如果CAbstract,那麼編譯器知道c.SelfAbstract的子類型,並且返回值可用於您希望的簽名的返回值可以使用的任何位置。如果CConcrete,則c.SelfConcrete。如果在上述示例中Cc1.type,則c2的類型仍然是Concrete