继这个问题之后,有人可以在Scala中解释以下内容:
class Slot[+T] (var some: T) {
// DOES NOT COMPILE
// "COVARIANT parameter in CONTRAVARIANT position"
}
Run Code Online (Sandbox Code Playgroud)
我明白之间的区别+T,并T在类型声明(它编译如果我使用T).但是,如何实际编写一个在其类型参数中具有协变性的类而不依赖于创建未参数化的东西?如何确保只能使用实例创建以下内容T?
class Slot[+T] (var some: Object){
def get() = { some.asInstanceOf[T] }
}
Run Code Online (Sandbox Code Playgroud)
编辑 - 现在得到以下内容:
abstract class _Slot[+T, V <: T] (var some: V) {
def getT() = { some }
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但我现在有两个类型参数,我只想要一个.我会再问这个问题:
如何编写一个在其类型中具有协变性的不可变 Slot类?
编辑2:呃!我用过var而不是val.以下是我想要的:
class Slot[+T] (val some: …Run Code Online (Sandbox Code Playgroud) public void wahey(List<Object> list) {}
wahey(new LinkedList<Number>());
Run Code Online (Sandbox Code Playgroud)
对方法的调用不会进行类型检查.我甚至无法将参数强制转换如下:
wahey((List<Object>) new LinkedList<Number>());
Run Code Online (Sandbox Code Playgroud)
根据我的研究,我收集到不允许这样做的原因是类型安全.如果允许我们执行上述操作,那么我们可以执行以下操作:
List<Double> ld;
wahey(ld);
Run Code Online (Sandbox Code Playgroud)
在方法wahey中,我们可以在输入列表中添加一些字符串(因为参数维护List<Object>引用).现在,在方法调用之后,ld引用一个带有类型的列表List<Double>,但实际列表包含一些String对象!
这似乎与没有泛型的Java正常工作方式不同.例如:
Object o;
Double d;
String s;
o = s;
d = (Double) o;
Run Code Online (Sandbox Code Playgroud)
我们在这里做的基本上是相同的,除了这将通过编译时检查,并且只在运行时失败.带有列表的版本将无法编译.
这让我相信这纯粹是关于泛型类型限制的设计决策.我希望对这个决定有所评论?
我已经尝试了这两段代码,但我两个都遇到了错误.下面附有两件作品和我得到的两个错误.如果发生这种情况,我将不胜感激.
例1
static List<String> list = new ArrayList<String>();
public static void main(String[] args) {
func(list);
}
private static void func(List<Object> lst) {
}
Run Code Online (Sandbox Code Playgroud)
错误:
The method func(List<Object>) in the type is not applicable for the arguments (List<String>)
例2
static List<Object> list = new ArrayList<Object>();
public static void main(String[] args) {
func(list);
}
private static void func(List<String> lst) {
}
Run Code Online (Sandbox Code Playgroud)
错误:
The method func(List<String>) in the type is not applicable for the arguments (List<Object>)