Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java接口对扩展抽象类的具体类的引用_Java_Class_Interface_Abstract - Fatal编程技术网

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

Java接口对扩展抽象类的具体类的引用,java,class,interface,abstract,Java,Class,Interface,Abstract,我试图理解为什么Java是这样工作的 假设我有: 界面-IAnimal 抽象类-哺乳动物 混凝土类-狗 哺乳动物实现了IAnimal和狗扩展了哺乳动物 interface IAnimal { public void feed(); } interface IMammal extends IAnimal { public void breastFeed(); } abstract class Mammal implements IMammal { @Override

我试图理解为什么Java是这样工作的

假设我有:

  • 界面-IAnimal
  • 抽象类-哺乳动物
  • 混凝土类-狗
  • 哺乳动物
    实现了
    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()");
        }
    }
    
    哺乳动物
    声明并实施方法
    母乳喂养()
    (当然
    动物
    没有此签名,因为并非所有动物都是哺乳动物)

    现在我想创建一个dog对象,接口将引用此dog,方法如下:

    IAnimal dog = new Dog();
    
    在运行时的某个地方,我可能想使用
    母乳喂养
    方法,但dog对象无法识别此方法

    一种解决方案是在
    Dog
    类中实现此方法 另一个解决方案是从实现接口的抽象类中引用
    Dog
    ,在本例中,我将所有内容都提供给Dog对象

    我觉得这些解决方案既混乱又怪异。有什么想法吗?也许我错过了什么,还有更好更干净的解决方案

    谢谢你,
    Yoav.

    这是有效的,因为您的继承链。但是这里的问题是dog被声明为
    IAnimal
    ,它只公开该接口拥有的方法,而不公开实现中的方法。如果需要访问
    母乳喂养()

    Mammal dog = new Dog();
    
    或者你可能想把你的
    扔给
    哺乳动物
    ,甚至是

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

    让我们假设在名为
    动物
    的包中有接口
    IAnimal
    、两个抽象类
    哺乳动物
    、两个具体类
    <代码>哺乳动物
    实现接口
    IAnimal
    ,而
    扩展
    哺乳动物
    扩展
    。这种情况如下所示(感谢@backslax的评论):

    界面:

    package animals;
    
    public interface IAnimal {
        void feed();
    }
    
    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!");
        }
    
    }
    
    抽象类:

    package animals;
    
    public interface IAnimal {
        void feed();
    }
    
    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!");
        }
    
    }
    
    哺乳动物:

    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 interface IAnimal {
        void feed();
    }
    
    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
    方法检查某个类的输出,如下所示:

    import animals.Dog;
    import animals.Eagle;
    import animals.IAnimal;
    
    public class Test {
    
        public static void main(String[] args) {
            IAnimal dog = new Dog();
            IAnimal eagle = new Eagle();
            dog.feed();
            eagle.feed();
        }
    
    }
    
    输出结果就是狗的行为。。。
    (请原谅生物学上的错误,可能有鸟类不给幼鸟喂食。这些例子是为java而做的,不是为大自然而做的…

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

    interface IAnimal{
        void feed();
    }
    
    abstract class Mammal implements IAnimal{}
    
    狗可能会吃一些肉:

    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();
    

    然后,您只需调用
    anemial.feed()
    。然后让实现来处理其余的部分。

    我将介绍一个扩展
    IAnimal
    的接口
    imal

    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()");
        }
    }
    

    然后,您可以在需要时测试IMammal的实例。

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

    例如:

    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();
        }
    
    }
    

    希望这能有所帮助。

    您可以简单地使用
    ((Dog)Dog)来调用它。母乳喂养()。然后你只需在你的
    IAnimal
    对象上调用
    feed()
    ,而
    母乳喂养()
    将自动在你的
    哺乳动物
    对象上调用。@Lino这只是一个例子,当然
    Dog
    类需要管理如何喂养狗。多态性的主要优点是,您不需要真正了解对象的行为,只需定义一个公共接口,每个类都有自己的实现。动物应该
    喂食
    :它如何喂食以及吃什么取决于特定的动物。这并没有增加任何内容,OP已经知道第一个“解决方案”,第二个“解决方案”已经由其他人提出。请完全删除
    哺乳动物类。并使
    母乳喂养()。如果可以,最好使用适当的继承。@Lino-还有可能
    哺乳动物
    会扩展一个抽象类
    动物
    。引入另一个中间类,对于当前的示例来说没有意义。但我同意你的观点,当哺乳动物有其他哺乳动物之间的共同状态,而不是动物之间的共同状态时