我创建了一个界面:
MyList<E> extends List<E>{
...
}
但是,当我尝试执行:MyList<_MyClass> = new LinkedList<_MyClass>()
时,出现编译错误。
如果MyList
根据定义包含List
中的所有方法,为什么我不能分配它?
如果我尝试强制转换它,我会得到一个运行时强制转换异常。
我错过了什么?
EDIT。感谢所有回复的人。我认为你可以将它与新的1.8默认方法一起使用,以便像C#扩展方法一样破解。即MyList有很多用于处理List的默认方法(没有其他方法),但我现在看到为什么这在概念上是不可能的。
答案 0 :(得分:3)
从更简单的界面来考虑它。
假设核心库有一个Animal接口。 还有一个名为Dog的实现。也就是说,Dog实现了Animal。
现在你来创建一个名为Human的动物的新实现。
Human也实现了Animal。
所以现在我可以做到这一点。
Animal a1, a2;
a1 = new Dog();
a2 = new Human();
但我不能这样做。
Human h = new Dog();
当然,人类和狗都是动物,但狗不可能代表人类。那是一个编译时例外。
现在你有一个稍微复杂的案例。
List是您的主界面,核心实现是LinkedList。也就是说,LinkedList实现了List。
因此扩展我的类比,你创建了一个名为HumanList的新类,它也扩展了List。
重复我以前做过的事,你可以做到这一点。
List<String> b1, b2;
b1 = new LinkedList<String>;
b2 = new HumanList<String>;
但你不能这样做。
HumanList<String> = new LinkedList<String>.
当然,HumanList和LinkedList都是List的实现。但是LinkedList在所有情况下都不能代表HumanList。
这是因为除了List接口之外,您的HumanList实现还可以使用其他方法,例如displaySocialSecurityNumbers()。
如果您的HumanList除了List之外没有其他方法,并且您永远不需要它,那么您可以执行以下操作。
List<E> b2 = new HumanList<E>();
最后,正如Xgord已经建议的那样,如果你想建议你的HumanList是一种LinkedList,那么你应该让HumanList扩展LinkedList。
答案 1 :(得分:2)
这是因为MyList
个对象不是LinkedList
类型的,这是您要分配的内容。
MyList
和LinkedList
都扩展List
,使其List
类型对象。但是,通过分配MyList<_MyClass> = new LinkedList<_MyClass>()
,您声明LinkedList
对象是MyList
对象,而实际情况并非如此。
将您的课程更改为:
MyList<E> extends LinkedList<E>{
...
}
它应该有用。
<强> 修改 强>
刚刚意识到我也成了Is-A陷阱的受害者。如果您执行MyList<E> extends LinkedList<E>
,那么您实际上需要将作业交换为:LinkedList<_MyClass> x = new MyList<_MyClass>()
答案 2 :(得分:1)
要添加@Teto所说的内容,它将会破坏Liskov Substitutuion Principle
可替代性是面向对象编程的一个原则 声明,在计算机程序中,如果S是T的子类型,那么 类型T的对象可以用类型S的对象替换(即, 类型T的对象可以用其子类型对象替换 类型S)而不改变任何所需的属性 程序(正确性,执行任务等)。
在您的情况下,MyList
可能会添加一些不属于List
的行为,因此不会成为LinkedList
的一部分。
因此LinkedList
无法取代MyList