Java多重继承
为了充分理解如何解决Java的多重继承问题,我有一个经典问题需要澄清 假设我有类Java多重继承,java,oop,multiple-inheritance,diamond-problem,multiple-interface-implem,Java,Oop,Multiple Inheritance,Diamond Problem,Multiple Interface Implem,为了充分理解如何解决Java的多重继承问题,我有一个经典问题需要澄清 假设我有类Animal这有子类Bird和Horse,我需要创建一个类Pegasus,它从Bird和Horse扩展而来,因为Pegasus既是鸟又是马 我认为这是典型的钻石问题。据我所知,解决这个问题的经典方法是使动物、鸟和马类接口,并从它们实现飞马 我想知道是否还有其他方法可以解决这个问题,我仍然可以为鸟和马创建对象。如果有一种方法也能创造动物,那将是很好的,但这不是必需的。你可以为动物类(生物学意义上的类)创建接口,例如为马
Animal
这有子类Bird
和Horse
,我需要创建一个类Pegasus
,它从Bird
和Horse
扩展而来,因为Pegasus
既是鸟又是马
我认为这是典型的钻石问题。据我所知,解决这个问题的经典方法是使动物
、鸟
和马
类接口,并从它们实现飞马
我想知道是否还有其他方法可以解决这个问题,我仍然可以为鸟和马创建对象。如果有一种方法也能创造动物,那将是很好的,但这不是必需的。你可以为动物类(生物学意义上的类)创建接口,例如为马创建
公共接口马类
,为鸟创建公共接口鸟类
(我不是生物学家,所以术语可能是错误的)
然后您仍然可以创建一个
public class Bird implements Avialae {
}
及
而且
public class Pegasus implements Avialae, Equidae {}
从评论中添加: 为了减少重复代码,您可以创建一个抽象类,其中包含要实现的动物的大部分公共代码
public abstract class AbstractHorse implements Equidae {}
public class Horse extends AbstractHorse {}
public class Pegasus extends AbstractHorse implements Avialae {}
更新 我想再补充一个细节。这是OP已经知道的
然而,我想强调的是,我建议绕过接口的“多重继承”问题,我不建议使用已经表示一个具体类型(如Bird)而更多表示一种行为的接口(其他接口指duck类型,这也很好,但我的意思是:birds的生物类Avialae)。我也不建议使用以大写字母“I”开头的接口名称,例如
IBird
,这并不能说明为什么需要接口。这就是问题的不同之处:使用接口构造继承层次结构,在有用时使用抽象类,在需要时实现具体类,并在适当时使用委托。从技术上讲,一次只能扩展一个类并实现多个接口,但是,当我着手研究软件工程时,我宁愿提出一个特定于问题的解决方案,而不是通常可以回答的。顺便说一句,这是一个很好的OO实践,不扩展具体类/只扩展抽象类以防止不必要的继承行为-没有“动物”这样的东西,也不使用动物对象,只使用具体的动物。接口不模拟多重继承。Java创建者认为多重继承是错误的,所以Java中没有这种东西
如果要将两个类的功能组合为一个类,请使用对象组合。即
public class Main {
private Component1 component1 = new Component1();
private Component2 component2 = new Component2();
}
如果要公开某些方法,请定义它们并让它们将调用委托给相应的控制器
这里的接口可能很方便-如果Component1
实现接口Interface1
和Component2
实现Interface2
,您可以定义
class Main implements Interface1, Interface2
因此,您可以在上下文允许的情况下互换使用对象
因此,在我看来,你不能陷入钻石问题。嗯,你的类可以是其他1个类的子类,但是,你仍然可以根据自己的意愿实现任意多的接口 帕伽索斯实际上是一匹马(这是马的特例),它能飞(这是这匹特殊马的“技能”)。从另一方面来说,你可以说,飞马是一种能走路的鸟,它有四条腿——这一切都取决于你如何更容易地编写代码 就像你的情况一样,你可以说:
abstract class Animal {
private Integer hp = 0;
public void eat() {
hp++;
}
}
interface AirCompatible {
public void fly();
}
class Bird extends Animal implements AirCompatible {
@Override
public void fly() {
//Do something useful
}
}
class Horse extends Animal {
@Override
public void eat() {
hp+=2;
}
}
class Pegasus extends Horse implements AirCompatible {
//now every time when your Pegasus eats, will receive +2 hp
@Override
public void fly() {
//Do something useful
}
}
您可以拥有一个接口层次结构,然后从所选接口扩展类:
public interface IAnimal {
}
public interface IBird implements IAnimal {
}
public interface IHorse implements IAnimal {
}
public interface IPegasus implements IBird,IHorse{
}
然后根据需要通过扩展特定接口来定义类:
public class Bird implements IBird {
}
public class Horse implements IHorse{
}
public class Pegasus implements IPegasus {
}
我有一个愚蠢的想法:
public class Pegasus {
private Horse horseFeatures;
private Bird birdFeatures;
public Pegasus(Horse horse, Bird bird) {
this.horseFeatures = horse;
this.birdFeatures = bird;
}
public void jump() {
horseFeatures.jump();
}
public void fly() {
birdFeatures.fly();
}
}
我可以提出一个新的概念吗 最有可能的是,你会让飞马扩展鸟和马的界面,但鸭子类型实际上表明你应该继承行为。正如评论中所说,飞马座不是鸟,但它能飞。所以你的飞马座应该继承一个
可飞的
-接口,比如说一个可飞的
-接口
这一概念被应用于实际工作中。给出的示例实际上向您展示了鸭子是如何继承
flybehavior
和quackbehavior
的,但仍然可能有鸭子,例如RubberDuck
,它们不能飞。他们还可以让鸭子扩展一个鸟类,但是他们会放弃一些灵活性,因为每只鸭子都能飞,即使是可怜的橡胶狗我想这在很大程度上取决于你的需要,以及你的动物类在你的代码中的使用方式
如果您希望能够在Pegasus类中使用Horse和Bird实现的方法和功能,那么您可以将Pegasus实现为鸟和马的一种组合:
public class Animals {
public interface Animal{
public int getNumberOfLegs();
public boolean canFly();
public boolean canBeRidden();
}
public interface Bird extends Animal{
public void doSomeBirdThing();
}
public interface Horse extends Animal{
public void doSomeHorseThing();
}
public interface Pegasus extends Bird,Horse{
}
public abstract class AnimalImpl implements Animal{
private final int numberOfLegs;
public AnimalImpl(int numberOfLegs) {
super();
this.numberOfLegs = numberOfLegs;
}
@Override
public int getNumberOfLegs() {
return numberOfLegs;
}
}
public class BirdImpl extends AnimalImpl implements Bird{
public BirdImpl() {
super(2);
}
@Override
public boolean canFly() {
return true;
}
@Override
public boolean canBeRidden() {
return false;
}
@Override
public void doSomeBirdThing() {
System.out.println("doing some bird thing...");
}
}
public class HorseImpl extends AnimalImpl implements Horse{
public HorseImpl() {
super(4);
}
@Override
public boolean canFly() {
return false;
}
@Override
public boolean canBeRidden() {
return true;
}
@Override
public void doSomeHorseThing() {
System.out.println("doing some horse thing...");
}
}
public class PegasusImpl implements Pegasus{
private final Horse horse = new HorseImpl();
private final Bird bird = new BirdImpl();
@Override
public void doSomeBirdThing() {
bird.doSomeBirdThing();
}
@Override
public int getNumberOfLegs() {
return horse.getNumberOfLegs();
}
@Override
public void doSomeHorseThing() {
horse.doSomeHorseThing();
}
@Override
public boolean canFly() {
return true;
}
@Override
public boolean canBeRidden() {
return true;
}
}
}
另一种可能是使用一种方法而不是遗传来定义你的动物。当然,这意味着您将不会有单独的Java动物类,而是只由它们的组件定义
实体组件系统方法的一些伪代码可能如下所示:
public void createHorse(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 4);
entity.setComponent(CAN_FLY, false);
entity.setComponent(CAN_BE_RIDDEN, true);
entity.setComponent(SOME_HORSE_FUNCTIONALITY, new HorseFunction());
}
public void createBird(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 2);
entity.setComponent(CAN_FLY, true);
entity.setComponent(CAN_BE_RIDDEN, false);
entity.setComponent(SOME_BIRD_FUNCTIONALITY, new BirdFunction());
}
public void createPegasus(Entity entity){
createHorse(entity);
createBird(entity);
entity.setComponent(CAN_BE_RIDDEN, true);
}
interface IFlier {
Flier getFlier();
}
class Bird extends Animal implements IFlier {
Flier flier = new Flier();
public Flier getFlier() { return flier; }
}
将对象组合在一起有两种基本方法:
- 第一个是继承。正如您已经确定的那样,继承的局限性意味着您不能在这里做您需要的事情
- 第二种是组合。由于继承失败,您需要使用组合
这样做的方式是,你有一个动物对象。然后在该对象中添加更多对象
class Bird extends Animal implements IFlier {
Flier flier = new Flier();
public Flier getFlier() { return flier; }
}
[abstract] class <clsname> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
interface <intf 0 name> extends <intf 1>,<intf 2>.........<intf n>
{
variable declaration cum initialization;
method declaration;
};
[abstract] class <derived class name> extends <base class name> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
class A {
void msg() {
System.out.println("From A");
}
}
class B {
void msg() {
System.out.println("From B");
}
}
class C extends A,B { // suppose if this was possible
public static void main(String[] args) {
C obj = new C();
obj.msg(); // which msg() method would be invoked?
}
}