Java 如何利用接口分离原理实现多态性?
我的目标是理解接口隔离原则,同时实现多态性 我的预期结果是:我可以使用接口分离原则实现多态性Java 如何利用接口分离原理实现多态性?,java,solid-principles,interface-segregation-principle,Java,Solid Principles,Interface Segregation Principle,我的目标是理解接口隔离原则,同时实现多态性 我的预期结果是:我可以使用接口分离原则实现多态性 public interface IWorker { void work(); void eat(); } class Human implements IWorker { public void work() { System.out.println("Human is working."); } public void eat() { Sy
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");
}
}
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
我的实际结果是:不,我不能。我被迫创建样板文件并使用Liskov替换原则(如果有工人,必须有不能吃的工人,所以为可以吃的工人创建一个扩展工人的接口)。我想我误解了接口隔离原则
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");
}
}
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
这是违反接口隔离原则的代码
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");
}
}
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
我被告知将接口分成两部分
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 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");
}
}
public interface IWorkable {
void work();
}
interface IEatable {
void eat();
}
interface IWorker extends IWorkable {
}
interface IHumanWorker extends IWorker, IEatable {
}
我建议使用抽象类,而不是接口。如果您需要每个
都可行,那么您可以将方法抽象化。如果他们只能选择吃东西,你就不能。这方面的一个例子是:
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
//多态性
List workers=Arrays.asList(新机器人(),新人类());
//做些工作
List-eaters=Arrays.asList(new-Human(),new-Human());
//派人去吃午饭
如果你想在同一件事情上同时拥有两种行为,那么你的抽象/设计似乎是错误的,因为机器人不能根据定义进食(由未实现方法的代码气味指示)
机器人不是IWorker(你的第一个代码),因为它不能完全满足(完整的)合同(接口、eat方法),不管它看起来有多相似。我不太明白你的问题是什么。使用IWorkable作为一个函数参数已经让我们使用多态性我认为这与Liskov替换原理相反?机器人不应该有吃法。还是LSP真的建议这样做?我喜欢在抽象类中假设方法错误的想法,因此您必须在每个新客户机上重写该方法。这就是robot没有eat方法的原因。我刚刚意识到我忘了发布输出,我会在再次使用电脑时编辑它。如果愿意,也可以在原始方法中抛出异常,重要的是不要重写robot类中的eat方法。我明白了,您可以在尽可能低的级别上使用接口(无需创建IWorker或IHumanWorker)。这就是我要找的,第一个代码不是问题。