Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.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_Inheritance_Interface - Fatal编程技术网

使用java继承和接口调用的方法版本不正确

使用java继承和接口调用的方法版本不正确,java,inheritance,interface,Java,Inheritance,Interface,我有一个简单的继承层次结构和一个接口。考虑类B将扩展B类。我希望这两个类实现接口I和类A是抽象的。在java中,我大致有以下几点: public interface I { public double foobar(); public void print(); } public abstract class A implements I { @Override public double foobar() { /*return foo*/} @Override

我有一个简单的继承层次结构和一个接口。考虑类B将扩展B类。我希望这两个类实现接口I和类A是抽象的。在java中,我大致有以下几点:

public interface I {
    public double foobar();
    public void print();
}

public abstract class A implements I {
    @Override public double foobar() { /*return foo*/}
    @Override public void print() {
        System.out.print(foobar());   
    }
}

public class B extends A {
    @Override public double foobar() { /*return bar*/ }
    @Override public void print() {
        super.print();
        System.out.print(foobar);
    }
}
我的意图是,当我实例化一个类型为B的对象并调用它的print()时,让类型为B的对象首先打印类A中的foo,然后打印类B中的bar;然而,当我编译一个执行此代码的程序时,它在这两种情况下都从类B调用foobar()。例如,如果foo等于1,bar等于2,则上述代码的输出如下:

public interface I {
    public double foobar();
    public void print();
}

public abstract class A implements I {
    @Override public double foobar() { /*return foo*/}
    @Override public void print() {
        System.out.print(foobar());   
    }
}

public class B extends A {
    @Override public double foobar() { /*return bar*/ }
    @Override public void print() {
        super.print();
        System.out.print(foobar);
    }
}
二, 二,

但我希望是这样 1. 二,

我曾尝试用各种类型的转换调用该方法,但没有成功。有什么建议吗

编辑:感谢您提出的许多建议,我只是想澄清一下,我希望A的每个潜在子类都实现I,我为没有明确说明这一点而道歉。此外,我目前通过在privateFooBar()中添加一个附加方法获得了工作代码,该方法由A的print和A的foobar调用;但是,我仍然想知道是否有更优雅的方法来完成这项任务。

foobar()
在类B中被重写。因此,每次对类B的实例调用它时,都会调用该方法的类B版本。这就是多态性的意义所在

如果希望A中的foobar()方法始终返回A的foobar版本,并且不希望子类中的方法更改该版本,则应在A中设置
foobar()

或者,您可以在以下位置委托给
private
方法:

public abstract class A implements I {
    @Override 
    public double foobar() { 
        return privateFoobar();
    }

    private double privateFoobar() {
        /* return foo */
    }

    @Override public void print() {
        System.out.print(privateFoobar());   
    }
}

public class B extends A {
    @Override public double foobar() { /*return bar*/ }
    @Override public void print() {
        super.print();
        System.out.print(foobar());
    }
}

在类A中,您正在调用foobar(),它在类B中被重写

public abstract class A implements I {
    @Override public double foobar() { /*return foo*/}
    @Override public void print() {
        System.out.print(foobar()); // HERE 
    }
}

您可以将该方法设置为最终方法,也可以将其设置为私有方法。这是通往foobar的一种迂回方式。您可以从B调用super.foobar(),并调整覆盖的print()方法。final或private不起作用,因为这样您就无法重写该方法。代码如下:

PS:我将返回类型更改为字符串以返回“foo”和“bar”:


由于类B重写了类A的foobar方法,所以类B总是调用类B版本的foobar

如果需要,类B将更改的方法行为,以便打印foo和bar的值,而不调用super.print()

为类B中的bar定义新方法,而不是重写类A的方法

public class B extends A {
    public double bar() { /*return bar*/ }
    @Override public void print() {
        System.out.print(bar());
        System.out.print(foobar());
    }
}

当您更改print()方法时,覆盖print()而不是foobar()方法是正确的。

您的调用代码在哪里?很抱歉没有显式编写我的调用代码。当我说“当我实例化一个类型为B的对象并调用它的print()”时,我指的是公共类X{public static void main(String[]args){B B=new B();B.print();}}}正好是5分钟前说的:)在发布之前忘记刷新页面,并且不能将其设置为私有。为了遵守基类契约,它必须是公共的。我使用了private方法选项,这是有效的,但是我很好奇,如果我将A的foobar()更改为final,是否必须更改子类B中的任何内容?为了提供上下文,我有一个类,它表示一家运输公司,方法foobar()表示一个CalculateCost()方法,该方法返回的值是发送相关包的成本的两倍。类A表示一个抽象方法,并具有CalculateCost()返回权重*每单位权重的成本。子类B的CalculateCost()返回父类的CalculateCost()添加到表示附加费的double中。我想知道是否有更好的方法如果
a.foobar()
是私有的,你不能在B中重写它。这就是final(关于方法)的意思。我说的“private method option”不是指将a.foobar()设为私有,而是按照上面的帖子中的建议,将另一个私有类设为privateFoobar。对不起,我的意思是“if a.foobar()是final”.谢谢你的澄清。最后一个想法是对上面的帖子的回应。我考虑了这个选项,但是在我的原始代码中,父的打印在很多文本的中间,并且要求我基本上重写PrimtUn的父代码,而不是调用AuP.Pr.To()。只需将其命名为.foobar()。没错,这意味着复制粘贴super.print()的大部分内容,但我相信您已经考虑过了。基本上,在print()中既有“foo”也有“bar”,只需为应用程序格式化即可。关于,-M。我也考虑过这个选项,但我被我的老师糟糕的措辞选择弄糊涂了,因为这是一个作业。他要求每个子类的实现I;然而,据我所知,编写公共类B扩展A实现是多余的。很抱歉,没有明确说明A的每个子类都应该实现I