在理解这两个原则时,我有些麻烦。这是一个长期阅读的问题,请耐心等待。
假设我们有一堂课
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
}
}
Circle没有任何面,因此为此孩子实现
SideCountable
听起来很荒谬。好的,我们只能将实现转移到“四边形”和“三角形”,但是在这种情况下,LSP将不再起作用。有人可以描述我应该怎么做的最好方法吗?SideCountable
保留在Shape
类中,并为Circle
返回0,并破坏接口隔离原理? SideCountable
移到Quad
和Triangle
并打破LSP原理? 最佳答案
首先,您的方法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
,这很好,因为尝试执行此操作对于一系列