Java 如何忽略/绕过重写的方法?

Java 如何忽略/绕过重写的方法?,java,polymorphism,overriding,Java,Polymorphism,Overriding,我对Java相当陌生,想知道如何完成以下任务,以及它是否被认为是糟糕的风格,即使它是可能的。多谢各位 Fish f; // Fish is a superclass, Tuna t = new Tuna(); // to which Tuna is a subclass. f=t; // the Fish object "f" now refers to the Tuna object "t". // Both Fish and Tuna have an identical metho

我对Java相当陌生,想知道如何完成以下任务,以及它是否被认为是糟糕的风格,即使它是可能的。多谢各位

Fish f;  // Fish is a superclass,
Tuna t = new Tuna();  // to which Tuna is a subclass.

f=t;  // the Fish object "f" now refers to the Tuna object "t".

// Both Fish and Tuna have an identical method (signature wise) called swim() ,
f.swim();  // and so Tuna's overridden swim() method is invoked here.
但是我现在可以使用相同的“
f.swim()
”语法调用Fish的swim()方法吗

编辑:

回复:答案,谢谢大家!关于SO用户Rinke在下面的回答,他说“您可以将您的Tunar实例分配给Tunar和fish类型的变量,但它始终是一个Tunar。”

这句话的最后一部分让我的新手大脑产生疑问——为什么要让“超级对象”指代“子对象”?这种灵活性的好处是什么?允许鱼对象在鱼或金枪鱼之间“切换”有什么好处?多谢各位

Fish f;  // Fish is a superclass,
Tuna t = new Tuna();  // to which Tuna is a subclass.

f=t;  // the Fish object "f" now refers to the Tuna object "t".

// Both Fish and Tuna have an identical method (signature wise) called swim() ,
f.swim();  // and so Tuna's overridden swim() method is invoked here.
编辑2:

下面是一些示例代码来说明SO用户Rinke的“编辑答案”响应的概念,如下所示

Bear b = new Bear();
Fish f = getAnyFish();
b.eat(f);

Fish getAnyFish(){
    //To toggle the returned fish type, change true to false
    if (true) return new Tuna();
    else return new Salmon();
}

如果重写了
Tuna.java
swim()
方法,则无法绕过该方法。 但您可以做的是,在重写的
swim()
中,在
Tuna.java
中,您可以调用super-class方法

Tuna.java

@Override
public void swim() {
   super.swim(); // This will call Fish.java's swim() method.
   // rest of the code
}
另一个选项是,更改
Tuna.java
swim()
方法的签名,使其成为
Fish.java
swim()
的重载版本,而不是被覆盖。

简短的回答是“否”。这里的混淆源于运行时类型和声明类型之间的差异。您可以将您的Tunar实例分配给Tunar和fish类型的变量,但它始终是一个Tunar。因此,如果您在该对象上调用swim方法,那么金枪鱼将像金枪鱼一样游动(即,将调用重写的方法)

请注意,可以通过调用super.swim()从子类中调用超类的swim方法

当然,如果不重写swim方法,那么金枪鱼只需从fish继承该方法。在这种情况下,fish代码将在tuna实例上运行

编辑答案:

您并不总是控制您使用的代码。也许您需要将您的金枪鱼提供给其他接受鱼的API

从相反的角度来看:也许你正在实现一个bear。熊吃鱼。你不想在意是金枪鱼还是鲑鱼。所以你得到了“空吃”(Fish f),大自然母亲(通过一段你无法控制的代码实现)为你的熊提供了鱼

留下有趣的鱼的例子:看看
Collections.sort()
。您可以对任何列表进行排序。不管它是ArrayList还是LinkedList

现在可以使用相同的方法调用Fish的swim()方法了吗 “f.swim()”语法


不,你不能。如果你真的想得到父类的swim方法,你可以使用不同的方法。 我将接口定义为Swimmable

public interface Swimmable {
    public void swim();
}
然后我让Fish实现这个接口

public class Fish implements Swimmable {

@Override
public void swim() {
    System.out.println("Fish");
    }
}
还有我的金枪鱼课

public class Tuna extends Fish {
//Anything I want the Tuna to have extra 
}
现在使用相同的代码

Fish f;
Tuna t = new Tuna();
f=t;
f.swim(); //This will call the Fish's method

虽然这是不可能的。
我使用@Deprecated来表示特定方法未使用。

也许我遗漏了一些东西,但是如果Tuna定义了自己的重写
swim()
,这难道不是
f.swim()
调用的吗?界面如何改变发生的任何事情?是的,正确。这就是为什么我没有在类Tuna中实现接口的原因,主要是因为海报的要求。因此,您的答案添加了一个接口,但没有执行OP要求的操作?我建议您尝试代码片段,看看它给出了什么结果。我同意您的答案,它可以按照广告的方式工作。我的问题是当
Tuna
还定义了
swim()
方法时,添加接口如何解决OP调用
Fish.swim()
的问题。