当前位置: 动力学知识库 > 问答 > 编程问答 >

scala - Overriding abstract type does not work with control abstraction

问题描述:

This question follows the one in Cake pattern with overriding abstract type don't work with Upper Type Bounds. I want to override the abstract type in trait with <:. The previous links gives the solution which consists in changing the order of linearization by writting this: Cake with S in trait S. However, I added a control abstraction named control in the following code. I want to call the method t in it.

trait A {

def ping = println("ping")

}

trait Cake {

type T

}

trait S { this: Cake with S =>

type T <: A with S

def t: T

def s = println("test")

// def control(c: =>T): T = c // compile

// def control(c: =>T): T = c.s // does not compile

def control(c: =>T): T = c.t // does not compile

t.ping

t.s

}

But, this code results in a compilation error that I can't explain

 found : S.this.T#T

required: S.this.T

def control(c: =>T): T = c.t

^

What is wrong ?

网友答案:
def control(c: =>T): T

Has return type S#T. Clearly, c has type T as well. Hence, returning c in:

def control(c: =>T): T = c

compiles, while returning c.s does not compile because s has return type of Unit. c.t does not compile because it has return type of S#T#T.

Thus, the following will compile:

def control(c: =>T): T#T = c.t

As the specifics behind everything that is happening here are a bit non-trivial in general, I suggest you google "type projection" and "path dependent types" for more information.

Essentially what is happening is c has type T, where T <: A with S, so we know T must have all of S's members, one of which is defined as def t: T. But this T is not necessarily the same as our T, so it does not conform when we call c.t in your example. What we want is the T of type T (or equivalently, T's T, or the T of our type member T). Here T#T indicates exactly what we want.

分享给朋友:
您可能感兴趣的文章:
随机阅读: