object ExistentialTypesAsFunctionParameters extends App{
def m(p: T forSome {type T})=p.toString
def m1(p:Any)=p.toString
println(m("Hello"))
println(m1("Hello"))
}
此程序运行并打印Hello
两次。
m
和m1
之间有什么区别,有没有?
与T forSome {type T}
相比,存在类型Any
允许的值是什么?
最重要的是:
如何根据Scala语言规范回答这些问题?
换句话说,需要对Scala语言规范进行解释。
编辑:
跟进问题:
class Top
class Middle extends Top {override def toString()="Middle"}
class Bottom extends Middle
object ExistentialTypesAsFunctionParameters extends App{
def m3(p: T forSome {type T >: Middle })=p.toString
println(m3(new Middle))
println(m3(new Bottom))
println(m3(new Top))
}
此代码编译并运行。
但是我希望println(m3(new Bottom))
不能编译,因为限制T forSome {type T >: Middle }
应该意味着任何类型可以是v
的子类型的值Middle
都不应该类型T forSome {type T >: Middle }
。
那么为什么这段代码仍然可以编译?
答案 0 :(得分:1)
p
中p.toString
的表达式类型是T forSome {type T}
的重新定义,符合SLS第6.1节:
以下的石油化规则适用于所有人 表达式:如果表达式的类型是存在类型 T,然后假设表达式的类型为a t。
的skolemization(§3.2.10)
我们可以看到Any
遵循你的引用中的skolemization规则。
因此当用作表达式的类型时,T forSome {type T}
与Any
具有相同的效果,并且它将允许相同的可能值。当作为一种类型使用时,如果它的特征化,它将被认为符合给定的类型(根据3.5.2)。但是类型不等同于3.5.1节中的定义。也就是说,即使在类型级别,我也看不出任何区分它们的方法。
编辑:T forSome {type T >: Middle}
只是Middle
的任何超类型,即Any
符合此类型。 Any >: Middle
所以Any <: T forSome {type T >: Middle}
和Bottom <: Any
,Bottom
仍然可以传递。如果要防止传递特定类型的子类型,可以使用对于这些子类型不存在的类型类(通过故意为这些子类型创建隐式解析冲突)。