3

この 2 つの原則を理解するのに苦労しています。これは少し長文の質問なので、しばらくお待ちください。

クラスがあるとしましょう

abstract class Shape {
    abstract void onDraw();
}

とインターフェース

interface SideCountable {
  int getSidesCount();
}

そして、2 つの子クラスを作成します。

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());
    }
}

そして、ここでやめたいと思います。なぜなら、実際には次のステップで立ち往生したからです。3 番目のクラスを作成するとどうなるでしょうCircleか。

class Circle extends Shape {

   public int getSidesCount() {
       return ???;
   }

   @Override
   public void onDraw() {
   //some draw logic here
   }
}

Circle には側面がないため、SideCountablefor this children の実装はばかげているように聞こえます。わかりました。実装を Quad と Triangle のみに移動できますが、この場合、LSP は機能しなくなります。誰かが私がすべき最善の方法を説明できますか?

  • クラスに残しSideCountableて0を返し、インターフェイスの分離原則を破りますか?ShapeCircle
  • 移行SideCountableQuadTriangleLSP の原則を破りますか?
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。代わりに、class を拡張する以外に、クラスを作成してインターフェイスQuadを実装します。TriangleSideCountableShape

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>に渡すことができますprintSidesCountSideCountable
  • List<Circle>to を渡すことはできませんprintSidesCount。これを行うことはサークルのリストには意味がないため、これは良いことです。
于 2019-12-17T10:34:33.020 に答える