Tujuan saya adalah untuk memahami Prinsip Pemisahan Antarmuka dan mencapai polimorfisme secara bersamaan.

Hasil yang saya harapkan: Saya dapat mencapai polimorfisme dengan Prinsip Pemisahan Antarmuka.

Hasil aktual saya: Tidak, saya tidak bisa. Saya dipaksa untuk membuat boilerplate dan menggunakan Prinsip Substitusi Liskov (Jika ada Worker, pasti ada Worker yang tidak bisa makan, jadi buat antarmuka untuk Worker yang bisa makan yang memperpanjang Worker). Saya pikir saya salah memahami Prinsip Pemisahan Antarmuka.

Ini adalah kode yang melanggar Prinsip Segregasi Antarmuka.

public interface IWorker {
  void work();
  void eat();
}

class Human implements IWorker {
  public void work() {
    System.out.println("Human is working.");
  }

  public void eat() {
    System.out.println("Human is eating.");
  }
}

class Robot implements IWorker {
  public void work() {
    System.out.println("Robot is working.");
  }

  public void eat() {
    throw new UnsupportedOperationException("Robot cannot eat");
  }
}

Saya disuruh memisahkan antarmuka menjadi 2.

public interface IEatable {
  void eat();
}

interface IWorkable {
  void work();
}

class Human implements IWorkable, IEatable {
  public void work() {
    System.out.println("Human is working.");
  }

  public void eat() {
    System.out.println("Human is eating.");
  }
}

class Robot implements IWorkable {
  public void work() {
    System.out.println("Robot is working.");
  }
}

Solusinya adalah dengan menggunakan Prinsip Substitusi Liskov.

public interface IWorkable {
  void work();
}

interface IEatable {
  void eat();
}

interface IWorker extends IWorkable {
}

interface IHumanWorker extends IWorker, IEatable {
}
2
kidfrom 24 Mei 2021, 19:29

2 jawaban

Jawaban Terbaik

Langkah kedua Anda terlihat bagus, Anda telah membagi antarmuka menjadi dua antarmuka yang lebih spesifik. Tidak masuk akal bagi Robot untuk "makan". (Saya tidak benar-benar mendapatkan langkah ketiga)

Di sisi penelepon, Anda sekarang dapat bekerja dengan abstraksi Anda:

//Polymorphism
List<IWorkable> workers = Arrays.asList(new Robot(), new Human());
//do some work

List<IEatable> eaters = Arrays.asList(new Human(), new Human());
//send for lunch break

Jika Anda ingin memiliki kedua perilaku dalam hal yang sama, maka abstraksi/desain Anda tampaknya salah, karena Robot tidak dapat makan menurut definisi (ditunjukkan oleh bau kode dari metode yang tidak diterapkan).

Robot bukan IWorker (kode pertama Anda), karena tidak memenuhi kontrak (penuh) (antarmuka, metode makan), tidak peduli seberapa miripnya.

1
HectorLector 25 Mei 2021, 06:32

Saya akan merekomendasikan menggunakan kelas abstrak dalam hal ini daripada antarmuka. Jika Anda membutuhkan setiap Workable untuk bekerja, maka Anda membuat metode menjadi abstrak. Jika hanya opsional yang mereka makan, Anda tidak. Contohnya adalah:

abstract class Workable {

    protected String name;

    public Workable(String name) {
        this.name = name;
    }

    protected abstract void work();

    public void eat() {
        System.err.println("\"" + name + "\" can't eat");
    }
}

class Human extends Workable {
    public Human(String name) {
        super(name);
    }
    @Override
    public void work() {
        System.out.println("Human " + name + " is working!");
    }

    @Override
    public void eat() {
        System.out.println("Human " + name + " is eating!");
    }
}

class Robot extends Workable {
    public Robot(String name) {
        super(name);
    }

    public void work() {
        System.out.println("Robot " + name + " is working!");
    }
}


public class Test {
    public static void main(String[] args) {
        Workable[] workers = new Workable[] {
                new Human("Jerry"),
                new Robot("XAE12")
        };
        for (Workable worker : workers) {
            worker.work();
            worker.eat();
        }
    }
}

Saya tidak yakin apakah saya memahami pertanyaan Anda dengan benar, jadi beri tahu saya jika itu membantu Anda.

0
Cactus Coder 24 Mei 2021, 17:49