Java接口对扩展抽象类的具体类的引用

时间:2018-07-04 12:48:25

标签: java class interface abstract

我试图理解Java为什么如此工作。

假设我有:

  1. 接口-IAnimal
  2. 抽象类-哺乳动物
  3. 具体课程-狗

Mammal实现IAnimal,而Dog扩展了Mammal

Mammal声明并实现方法breastFeed()(当然,Animal没有此签名,因为并非每只动物都是哺乳动物)

现在,我想创建一个狗对象,接口将以这种方式引用该狗:

IAnimal dog = new Dog();

在运行时的某个地方,我可能想使用breastFeed方法,但是dog对象无法识别该方法。

一种解决方案是在Dog类中实现此方法 其他解决方案是从Abstract类引用Dog,该类实现了接口,在这种情况下,我将所有内容都交给dog对象。

我发现这些解决方案是混乱而又怪异的。有什么想法吗?也许我错过了一些东西,并且有一些更好更清洁的解决方案?

谢谢你, 耶夫。

6 个答案:

答案 0 :(得分:0)

这是有效的,因为您有继承链。但是这里的事情是dog被声明为IAnimal,它只公开该接口具有的方法,而不公开实现中的方法。如果需要访问breastFeed()方法,则应将值强制转换为子类。

答案 1 :(得分:0)

让我们假设您在名为{{的程序包]中拥有接口IAnimal,两个抽象类MammalBird以及两个具体类DogEagle 1}}。 animalsMammal实现了接口Bird,而IAnimal扩展了Dog,而Mammal扩展了Eagle。这种情况如下所示(感谢@BackSlash的评论):

接口:

Bird

抽象类:

哺乳动物:

package animals;

public interface IAnimal {
    void feed();
}

鸟:

package animals;

abstract class Mammal implements IAnimal {

    /*
     * This is the feeding method that every animal has to implement.
     * The trick here is to force the inconcrete method feed() to use the
     * mammal specific one that has to be implemented by concrete mammals
     */
    @Override
    public void feed() {
        breastFeed();
    }

    /*
     * This is how mammals feed,
     * so every concrete mammal has to implement this method (even humans...)
     */
    protected abstract void breastFeed();
}

具体课程:

package animals;

public abstract class Bird implements IAnimal {

    /*
     * This time, force the inconcrete method feed() to use the
     * bird specific one that has to be implemented by concrete birds
     */
    @Override
    public void feed() {
        feedPrey();
    }

    /*
     * Birds feed prey to their young, most likely due to a lack of breasts
     */
    protected abstract void feedPrey();
}

您可以使用package animals; public class Dog extends Mammal { /* * This is how dogs feed, the implementation of how mammals feed */ @Override protected void breastFeed() { System.out.println("currently breastfeeding... do not disturb!"); } } 这样的方法检查某个类的输出:

main

,输出将是狗的行为... (请原谅生物学上的错误,可能有些鸟没有给它们的幼崽喂食。这些例子是为爪哇而不是自然而生的。)

答案 2 :(得分:0)

您应该完全忘记方法breastFeed,因为这只是一个规范。只需将方法feed()添加到IAnimal中,然后让实现决定它们的食用方式:

interface IAnimal{
    void feed();
}

abstract class Mammal implements IAnimal{}

Dog可能会吃一些肉:

class Dog extends Mammal{
     public void feed(){
         System.out.println("Eating meat!");
     }
}

BabyCat可能会喝一些牛奶:

class BabyCat extends Mammal{
     public void feed(){
         System.out.println("Drinking milk!");
     }
}

这是要走的路,所以在声明狗时如下:

IAnimal animal = new Dog();

然后您可以致电anmial.feed()。然后让其他实现来处理。

答案 3 :(得分:0)

我将介绍扩展IMammal的接口IAnimal

interface IAnimal {
    public void feed();
}

interface IMammal extends IAnimal {
    public void breastFeed();
}

abstract class Mammal implements IMammal {

    @Override
    public void feed() {
        breastFeed();
    }

}

class Dog extends Mammal {

    @Override
    public void breastFeed() {
        System.out.println("Dog breastFeed()");
    }
}

然后可以在需要时测试instanceof IMammal

答案 4 :(得分:0)

我不会在这里使用接口,因为所有行为都是继承的。但是,使用IAnimal dog = new Dog();狗只能访问IAnimal方法。因此,如果要将dog存储到Mammal变量中,则可以访问breastFeed()方法。

例如:

public abstract class Animal {
    public abstract void feed();
}

public abstract class Mammal extends Animal {
    public abstract void breastFeed();
}

public class Dog extends Mammal{

    @Override
    public void breastFeed() {
        System.out.println("Drinking milk!");
    }

    @Override
    public void feed() {
        System.out.println("Eating meating");
    }

}

public class TryingAnimal {

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.breastFeed();
        dog.feed();

        Animal animal = dog;
        animal.feed();

        Mammal mammal = dog;
        mammal.breastFeed();
    }

}

希望这会有所帮助。

答案 5 :(得分:-2)

您可能想将变量声明为Mammal,例如EG:

Mammal dog = new Dog();

或者您可能希望将dog投射为Mammal甚至是Dog

if (dog instanceof Mammal)
  ((Mammal) dog).breastFeed();