Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
622 views
in Technique[技术] by (71.8m points)

scala - Cake pattern with overriding abstract type don't work with Upper Type Bounds

I want to override abstract type in trait with <: and not with = (like answer here Scala Upper Bounds : value is not a member of type parameter).

I want to use cake pattern, but this doesn't work, i don't understand why ?

trait A {
  def ping = println("ping")
}

trait Cake {
  type T
}

trait S { this: Cake =>
  type T = A
  def t: T
  t.ping
}

OK, this example run, but in my real use case i want to override type with <: and not with = .It seems impossible to access the t function, why ?

trait S { this: Cake =>
  type T <: A
  def t: T
  t.ping
}

return an error value ping is not a member of S.this.T

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's a shortcoming of Scala's type system. When determining the members in a mixin, Scala uses two rules: First, concrete always overrides abstract. Second, If two members are both concrete, or both abstract, then the one that comes later in linearization order wins.

Furthermore, the self type of a trait

trait S { this: C => ... }

is implicitly augmented to

trait S { this: S with C => ... }

so that definitions in the trait S can be accessed within S. In your case, the trait S is seen as:

trait S { this: S with Cake =>
  type T = A
  def t: T
  t.ping
}

Now, as long as T is concrete this is fine because it overrides the abstract T in Cake. But if T is abstract, the one in Cake cames later in the linearization order and wins. And that T does not have an upper bound, so no member ping. One way to fix this is to change the linearization order by writing:

trait S { this: Cake with S =>
  type T <: A
  def t: T
  t.ping
}

It would be cleaner if Scala had a different rule that says that all constraints of abstract type members are merged in the mixin, instead of picking a single member according to linearization order. That's a change we want to consider in the future, but we need to be careful with backwards compatibility.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...