如何用接口隔离原则实现多态?
How to achieve polymorphism with the Interface Segregation Principle?
我的目标是理解接口隔离原则,同时实现多态。
我的预期结果:我可以用接口隔离原则实现多态
我的实际结果:不,我不能。我被迫创建样板并使用 Liskov 替换原则(如果有一个 Worker,则必须有一个不能吃的 Worker,因此为可以吃的 Worker 创建一个扩展 Worker 的接口)。我想我误解了接口隔离原则。
这是违反接口隔离原则的代码。
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");
}
}
我被告知将界面分成 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.");
}
}
解决方案是使用 Liskov 替换原则。
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
我建议为此使用抽象 类 而不是接口。如果您需要每个 Workable
都起作用,那么您可以将方法抽象化。如果他们吃东西只是可选的,那么你就不会。一个例子是:
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();
}
}
}
我不确定我是否正确理解了你的问题,如果对你有帮助请告诉我。
你的第二步看起来不错,你将界面拆分为两个更具体的界面。机器人“吃”是没有意义的。 (第三步我真的不懂)
在调用方,您现在可以使用您的抽象:
//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
如果你想在同一件事上同时拥有这两种行为,那么你的 abstraction/design 似乎是错误的,因为根据定义机器人不能吃东西(由未实现方法的代码味道表示)。
机器人不是 IWorker(你的第一个代码),因为它没有完全填充(完整)契约(接口,吃方法),无论它看起来多么相似。
我的目标是理解接口隔离原则,同时实现多态。
我的预期结果:我可以用接口隔离原则实现多态
我的实际结果:不,我不能。我被迫创建样板并使用 Liskov 替换原则(如果有一个 Worker,则必须有一个不能吃的 Worker,因此为可以吃的 Worker 创建一个扩展 Worker 的接口)。我想我误解了接口隔离原则。
这是违反接口隔离原则的代码。
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");
}
}
我被告知将界面分成 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.");
}
}
解决方案是使用 Liskov 替换原则。
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
我建议为此使用抽象 类 而不是接口。如果您需要每个 Workable
都起作用,那么您可以将方法抽象化。如果他们吃东西只是可选的,那么你就不会。一个例子是:
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();
}
}
}
我不确定我是否正确理解了你的问题,如果对你有帮助请告诉我。
你的第二步看起来不错,你将界面拆分为两个更具体的界面。机器人“吃”是没有意义的。 (第三步我真的不懂)
在调用方,您现在可以使用您的抽象:
//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
如果你想在同一件事上同时拥有这两种行为,那么你的 abstraction/design 似乎是错误的,因为根据定义机器人不能吃东西(由未实现方法的代码味道表示)。
机器人不是 IWorker(你的第一个代码),因为它没有完全填充(完整)契约(接口,吃方法),无论它看起来多么相似。