Concrete classes with abstract type members
Given the following traits and class. Why does this compile? Can this be 开发者_运维知识库actually used for something?
trait Container {
type A
}
trait AnotherContainer[B]{
def x(b : B) : B
}
trait Mixed extends Container with AnotherContainer[Container#A]
class Impl extends Mixed{
def x(a : Container#A) = a
}
new Impl().x _
scala> new Impl().x _
res0: (Container#A) => Container#A = <function>
Update:
class Baz { type T; }
Is actually a feature but I could not find the motivation for it: #1753.
In your example, the compiler adds the default type bounds of >: Nothing <: Any
. The second example below shows a case where an abstract type becomes usable (if not useful).
scala> trait T { type A >: Nothing <: Any }
defined trait T
scala> 1: T#A
<console>:6: error: type mismatch;
found : Int(1)
required: T#A
1: T#A
^
scala> trait T { type A >: Int <: Int }
defined trait T
scala> 1: T#A
res6: T#A = 1
scala> "": T#A
<console>:6: error: type mismatch;
found : java.lang.String("")
required: T#A
"": T#A
^
It looks harmless if useless to me. The type that x wants doesn't exist, so you can't pass it to the method. Whether harmless uselessness should be a compile-time error is a matter of taste, I suppose.
If you look at what x actually does, it decompiles thusly:
public java.lang.Object x(java.lang.Object);
Code:
0: aload_1
1: areturn
which is exactly what the identity method should do (load the argument regardless of type, return it). You can write something equivalent with much less code:
trait AbstractType { type T }
class Useless extends AbstractType { def identity(t: AbstractType#T) = t }
Except nothing has type AbstractType#T, so again we have uselessness.
Unless I'm missing something.
精彩评论