为什么以下不能在Scala中编译:
class A
class B
object X {
def f[Q <: A](q: Q): Q = q
def f[Q <: B](q: Q): Q = q
}
Run Code Online (Sandbox Code Playgroud)
有错误消息
<console>:16: error: method f is defined twice
conflicting symbols both originated in file '<console>'
def f[Q <: B](q: Q): Q = q
Run Code Online (Sandbox Code Playgroud)
据我所知,在类型擦除之后,def f[Q <: A](q: Q): Q应该用它的上限替换:def f(q: A): Any第二次f相应地重载.所以在类型擦除后它们应该是可区分的.
那么为什么Scala还在抱怨?
让我们用抽象类定义一个特征
object Outer {
trait X {
type T
val empty: T
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以创建它的一个实例:
val x = new X {
type T = Int
val empty = 42
}
Run Code Online (Sandbox Code Playgroud)
Scala现在承认,这x.empty是Int:
def xEmptyIsInt = x.empty: Int
Run Code Online (Sandbox Code Playgroud)
现在,让我们定义另一个类
case class Y(x: X) extends X {
type T = x.T
val empty = x.empty
}
Run Code Online (Sandbox Code Playgroud)
并制作一个实例
val y = Y(x)
Run Code Online (Sandbox Code Playgroud)
但现在Scala,无法推断出y.empty类型Int.下列
def yEmptyIsInt = y.empty: Int
Run Code Online (Sandbox Code Playgroud)
现在生成错误消息:
error: type mismatch;
found : y.x.T
required: Int …Run Code Online (Sandbox Code Playgroud) 根据http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#volatile-types,类型在符合特定条件时是易变的.是否有可能使类型不易变形(例如通过注释)?有什么可能的选择吗?
我的用例如下:我想编写一个库,它暴露类型A和Bwith A <: B并且B是volatile.然后作为此库的用户,我希望能够A使用以下类型之一覆盖类型的值B:
trait TraitB {
def doSomething: Unit
}
trait Library {
type A
type B <: A with TraitB
}
object LibraryUser {
val library: Library = ???
trait T {
val x: library.A
}
object U extends T {
val x: library.B = ???
}
}
Run Code Online (Sandbox Code Playgroud)
这失败并出现错误:
错误:覆盖类型LibraryUser.library.A的特征T中的值x; 值x具有易失性类型; 不能覆盖非易失性类型的成员
但是,当我A挥发时,这成功了.目前,我A通过使它成为抽象类型的子类来实现volatile,它Abstract只是Any在实现中,否则不会被使用:
trait TraitB { …Run Code Online (Sandbox Code Playgroud) 我知道Scala中的volatile类型可以用来建模
类型参数或类型的抽象类型实例不具有任何非空值的可能性
(http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#volatile-types)
但究竟是什么问题呢?是否有一个使用@uncheckedStable(例如http://www.scala-lang.org/files/archive/spec/2.11/11-annotations.html#scala-compiler-annotations)生成不安全代码的示例?
有没有什么办法,去的类型A从Some[A]?
type X = Some[Int]
type Y = ??? // what do I have to write here to get `Int`
Run Code Online (Sandbox Code Playgroud)
我可以定义自己的Option类型,允许这样:
sealed trait Option[+A]
case object None extends Option[Nothing]
case class Some[+A](a: A) {
type Inner = A
}
Run Code Online (Sandbox Code Playgroud)
然后使用
type X = Some[Int]
type Y = X#Inner
Run Code Online (Sandbox Code Playgroud)
对于普通的Scala Option类型,这也可以吗?