在理解这两个原则时,我有些麻烦。这是一个长期阅读的问题,请耐心等待。
让我们假设我们有一个课
abstract class Shape {
abstract void onDraw();
}
和界面
interface SideCountable {
int getSidesCount();
}
然后我们创建两个子类
class Quad extends Shape {
@Override
public void onDraw() {
//some draw logic here
}
}
class Triangle extends Shape {
@Override
public void onDraw() {
//some draw logic here
}
}
现在我们将使Shape
实现SideCountable
abstract class Shape implements SideCountable{
abstract void onDraw();
}
并在儿童班上进行更改
class Quad extends Shape {
@Override
public int getSidesCount() {
return 4;
}
@Override
public void onDraw() {
//some draw logic here
}
}
class Triangle extends Shape {
public int getSidesCount() {
return 3;
}
public void onDraw() {
//some draw logic here
}
}
并为此结构创建测试功能(遵循LSP):
public void printSidesCount(List<Shape> shapes) {
for(int i=0; i < shapes.size(); i++) {
System.out.println(shapes.get(i).getSidesCount());
}
}
在这里我想停止,因为实际上在下一步中我被卡住了。
如果我们要创建第三类Circle
怎么办?
class Circle extends Shape {
public int getSidesCount() {
return ???;
}
@Override
public void onDraw() {
//some draw logic here
}
}
圆没有边,因此为这个孩子实施SideCountable
听起来很荒谬。好的,我们只能将实现转移到“四边形”和“三角形”,但是在这种情况下,LSP将不再起作用。有人可以描述我应该怎么做的最好方法吗?
SideCountable
留在Shape
类中,并为Circle
返回0并打破接口隔离原则?SideCountable
移至Quad
和Triangle
并打破LSP原理吗?答案 0 :(得分:2)
首先,您的方法printSidesCount
只需要知道该列表包含SideCountable
个对象。因此,为其参数指定类型List<Shape>
比必要的更为具体。改用List<SideCountable>
:
public void printSidesCount(List<SideCountable> sideCountables) {
for(int i=0; i < (); i++) {
System.out.println(sideCountables.get(i).getSidesCount());
}
}
甚至是List<? extends SideCountable>
,它的意思是“实现SideCountable
的任意未知类型的列表”:
public void printSidesCount(List<? extends SideCountable> sideCountables) {
for(int i=0; i < sideCountables.size(); i++) {
System.out.println(sideCountables.get(i).getSidesCount());
}
}
如果不是所有形状的边数都可数,则类Shape
不应实现接口SideCountable
。相反,使类Quad
和Triangle
除了扩展类SideCountable
之外,还实现接口Shape
:
class Quad extends Shape implements SideCountable {
// ...
}
class Triangle extends Shape implements SideCountable {
// ...
}
并使类Circle
扩展Shape
但不实现SideCountable
:
class Circle extends Shape { // Not SideCountable
// ...
}
当您这样做时,类型系统将为您提供帮助:
List<Quad>
或List<Triangle>
传递给printSidesCount
,因为这些类型实现了SideCountable
List<Circle>
传递给printSidesCount
,这很好,因为尝试这样做对圈子列表没有意义