3

我在理解这两个原则时遇到了一些麻烦。这是一个有点长的阅读问题,所以请耐心等待。

假设我们有一个类

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 将不再工作。有人可以描述我应该做的最好的方法吗?

  • SideCountableShape归0为Circle打破接口隔离原则?
  • 迁移SideCountableQuad打破TriangleLSP原理?
4

1 回答 1

3

首先,您的方法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不应该实现 interface SideCountable。相反,除了扩展类之外,还创建类QuadTriangle实现接口:SideCountableShape

class Quad extends Shape implements SideCountable {
    // ...
}

class Triangle extends Shape implements SideCountable {
    // ...
}

并使类Circle扩展Shape但不实现SideCountable

class Circle extends Shape { // Not SideCountable
    // ...
}

当您这样做时,类型系统将帮助您:

  • 您可以传递 a List<Quad>or List<Triangle>toprintSidesCount因为这些类型实现SideCountable
  • 你不能传递 a List<Circle>to printSidesCount,这很好,因为尝试这样做对于圈子列表没有意义
于 2019-12-17T10:34:33.020 回答