2013-11-28 3 views
2

Я довольно новичок в 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()» синтаксис?

// I would now like Fish's swim() method to be invoked here, 
// but is it bad style and/or am I missing some point about OOP? 
f.swim(); 

Edit:

Re: ответы, спасибо люди! Что касается ответа SO пользователя Rinke ниже, он заявляет, что «вы можете назначить свой экземпляр тунца как переменным тунца, так и рыбы, но он всегда будет тунцом».

Последняя часть этого предложения заставила моего начинающего мозг OOD удивляться: почему позволить «супер-объекту» ссылаться на «под-объект»? Какая польза от этой гибкости? Какая польза в том, чтобы позволить Рыбному объекту «переключаться между» или «рыбой» или тунцом? Спасибо.

Edit 2:

Вот несколько примеров кода, чтобы проиллюстрировать концепцию так что пользователь 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(); 
} 

ответ

2

Короткий ответ: «Нет». Путаница здесь проистекает из разницы между типами времени выполнения и объявленными типами. Вы можете назначить свой экземпляр тунца как для тунца, так и для рыбных типизированных переменных, но он всегда будет тунцом. Следовательно, если вы назовете метод плавания на этом объекте, тунец будет плавать, как тунец (т. Е. Будет вызван переопределенный метод).

Обратите внимание: может вызывать метод плавания суперкласса из подкласса, вызывая super.swim().

Конечно, если вы не переопределяете метод плавания, то тунцы просто наследуют метод от рыбы. В этом случае код рыбы будет запущен на примере тунца.

Ответ на редактирование:

Вы не всегда контролировать код, который вы используете. Возможно, вам нужно предоставить свой тунн в чужой API, который принимает рыбу.

С другой стороны: возможно, вы внедряете медведя. Медведи едят рыбу. Вы не хотите заботиться о том, является ли это тунцом или лососем.Таким образом, вы получаете void eat(Fish f), где природа матери (реализуемая частью кода вне вашего контроля) обеспечивает рыбу вашему медведю.

Чтобы оставить пример забавной рыбы: посмотрите на Collections.sort(). Вы можете отсортировать список. Не имеет значения, является ли это ArrayList или LinkedList.

1

Вы не можете перепускной Tuna.java «s swim() метод, если он переопределен. Но что вы можете сделать, в переопределенном swim(), внутри Tuna.java, вы можете сделать вызов метода суперкласса.

Tuna.java

@Override 
public void swim() { 
    super.swim(); // This will call Fish.java's swim() method. 
    // rest of the code 
} 

Другой вариант, изменить подпись swim() метода в Tuna.java таким образом, что она становится перегруженной версией Fish.java «s swim(), но не переопределен ,

1

Могу ли я теперь вызвать метод плавания рыбы(), используя тот же "f.swim()" синтаксис?

Нет, вы не можете.

0

Вы можете использовать другой подход к этому, если вы действительно хотите получить метод плавания родительского класса. я определить интерфейс, как 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 
+0

Возможно, мне не хватает что-то, но если Tuna определяет свой собственный переопределяющий 'swim()', не будет ли это то, что вызывает 'f.swim()'? Как интерфейс меняет все, что происходит? – Teepeemm

+0

Да, правильно. Вот почему я не реализовал интерфейс в классе Tuna в основном из-за требования плаката. –

+0

Итак, ваш ответ добавляет интерфейс, но не делает то, что спросил OP? – Teepeemm

 Смежные вопросы

  • Нет связанных вопросов^_^