Ada*_*ler 2 java types scala existential-type type-bounds
根据THE Java Programming Language 4th ed.第15.7.1节"类型代币":
getClass接受编译器的特殊处理:如果在具有静态类型 T的引用上调用 getClass,则编译器将 getClass的返回类型视为 Class.这样可行:
String str = "Hello";
Class<? extends String> c2 = str.getClass(); // compiler magic
Run Code Online (Sandbox Code Playgroud)
类中方法的javadoc提供了getClassObject更多细节:
[实际结果类型
getClass()]是Class<? extends |X|>其中|X|是静态类型在其上的getClass称为表达的擦除.例如,此代码片段中不需要强制转换:Run Code Online (Sandbox Code Playgroud)Number n = 0; Class<? extends Number> c = n.getClass();
这是Java和getClass()类的方法Object.将注意力转向Scala,SLS 3.2.10读取,
存在类型的占位符语法
句法:
Run Code Online (Sandbox Code Playgroud)WildcardType ::= ‘_’ TypeBoundsScala支持存在类型的占位符语法.甲通配符类型的形式是_>:L <:U ...一个通配符类型是用于存在性量化型变量,其中存在量化是隐式的简写.
...设T = pc [targs,T,targs']是参数化类型,其中targs,targs'可能为空,T是通配符类型_>:L <:U.然后T相当于存在类型
pc [targs,t,targs] forSome { type t>:L <:U }
其中t是一些新的变量.
我强调"T等同于存在主义类型......"因为我观察到的行为似乎与该陈述不一致.
在Scala repl中,我尝试了SLS 3.2.10的通配符语法:
scala> val c: Class[_ >: scala.Nothing <: String] = "foo".getClass
c: Class[_ <: String] = class java.lang.String
Run Code Online (Sandbox Code Playgroud)
这符合我的预期.但是,如果我依赖于SLS 3.2.10中声称的"通配符类型是存在量化类型变量的简写",我会遇到意外的失败.
scala> val c: Class[t forSome { type t >: scala.Nothing <: String }] = "foo".getClass
<console>:7: error: type mismatch;
found : java.lang.Class[?0] where type ?0 <: java.lang.String
required: Class[t forSome { type t <: String }]
Note: ?0 <: t forSome { type t <: String }, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: t forSome { type t <: String }`. (SLS 3.2.10)
val c: Class[t forSome { type t >: scala.Nothing <: String }] = "foo".getClass
^
Run Code Online (Sandbox Code Playgroud)
错误消息似乎正在引导我递归回到SLS 3.2.10,建议我同时使用通配符语法和快速存在量化.我不明白这意味着什么.无论如何,我使用Object上面引用的javadoc中的示例观察到相同的二分法:
scala> val n: Number = 0
n: java.lang.Number = 0
Run Code Online (Sandbox Code Playgroud)
作品:
scala> val c: Class[_ >: scala.Nothing <: Number] = n.getClass
c: Class[_ <: java.lang.Number] = class java.lang.Integer
Run Code Online (Sandbox Code Playgroud)
不起作用:
scala> val c: Class[t forSome { type t >: scala.Nothing <: Number }] = n.getClass
<console>:8: error: type mismatch;
found : java.lang.Class[?0] where type ?0 <: java.lang.Number
required: Class[t forSome { type t <: java.lang.Number }]
Note: ?0 <: t forSome { type t <: java.lang.Number }, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: t forSome { type t <: java.lang.Number }`. (SLS 3.2.10)
val c: Class[t forSome { type t >: scala.Nothing <: Number }] = n.getClass
Run Code Online (Sandbox Code Playgroud)
如果特定的通配符类型与特定的存在类型"等效",那是否意味着可以替换另一个?这不是等价的意思吗?假设我正确理解SLS 3.2.10中使用的"等价"含义,我是否在根据SLS 3.2.10中规定的规则进行等效替换时出错?如何处理我在上面引用的包含与SLS 3.2.10一致的存在类型的两个语句的失败,根据这些语句,失败的语句等同于使用成功的通配符类型的语句?
有问题的错误消息的必需行和找到行中指定的类型之间有什么区别?也就是说,这是怎么回事:
java.lang.Class[?0] where type ?0 <: java.lang.String
Run Code Online (Sandbox Code Playgroud)
不同于
Class[t forSome { type t <: String }]
Run Code Online (Sandbox Code Playgroud)
第一个问题是什么?显然?0意味着什么,它似乎是一个类型变量,但使用像这样的问号不是Scala,是吗?它是什么语言,它在哪里指定,所以我能理解错误信息?
再看一下你引用的规范部分:
设T = pc [targs,T,targs']是参数化类型,其中targs,targs'可以为空,T是通配符类型_>:L <:U.那么T相当于存在类型pc [targs,t,targs] forSome {type t>:L <:U}其中t是一些新的类型变量.
特别要注意它的说法p.c[targs, t , targs ] forSome { type t >: L <: U }而不是 p.c[targs, t forSome { type t >: L <: U } , targs ].这两种类型是不同的.
回到Class它的上下文意味着Class[_ >: scala.Nothing <: String]相当于Class[t] forSome { type t >: scala.Nothing <: String},而不是 Class[t forSome { type t >: scala.Nothing <: String }].
果然,如果你在REPL中输入以下内容,它会很好:
val c: Class[t] forSome { type t >: scala.Nothing <: String } = "foo".getClass
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
835 次 |
| 最近记录: |