2013-05-28 4 views
2

Я недавно столкнулся со следующим сценарием:Полиморфизм и перегрузка

У меня есть суперкласс A и класс B, вытекающие из него. Функция, например oracle, возвращает объект любого типа. Я хочу делать разные вещи в зависимости от типа, но я не могу ввести новую функцию-член для A и B.

Одним из решений является ветвление в соответствии с getClass(). GetName(). Тем не менее, мне было интересно, может ли полиморфизм добиться такого же поведения с помощью перегрузки:

public class Main 
{ 
    static class A{} 
    static class B extends A{} 

    public static void foo(A a) { System.out.println("A"); }; 
    public static void foo(B b) { System.out.println("B"); }; 

    static A oracle() 
    { 
     return (Math.random() > 0.5) ? new A() : new B(); 
    } 

    public static void main(String[] args) 
    { 
     A x = oracle(); 
     foo(x); 
    } 
} 

Это всегда выводит «А» и мое подозрение, что это из-за раннего связывания используется для разрешения вызовов функций. Может ли кто-нибудь признать это?

+2

Вы передаете ему переменную типа 'A', поэтому он вызывает метод, чья подпись принимает' A'. Я думаю, что единственный способ использовать getClass(). GetName() ', как вы упомянули. – iamnotmaynard

+0

@iamnotmaynard Я бы написал это как решение (немного более подробно, возможно). – SJuan76

+0

Точно. Если вам абсолютно необходимо, вы можете использовать оператор 'instanceof' для включения фактического типа объектов.Но лучше OO-Design поставить 'foo()' внутри классов A и B (поэтому объекты знают, что сказать «)» –

ответ

3

В технических терминах Java является с одной отправкой Язык ООП. Это означает, что решение во время выполнения, которое метод для вызова (метод отправки) учитывает только первый аргумент метода — тот, что находится слева от точки. Там вы можете увидеть, как этот принцип настолько глубоко укоренился в языке, что первый аргумент даже получает специальное синтаксическое лечение.

Следовательно, нет, вы не можете выполнить полиморфизм во время выполнения с перегрузкой.

+0

Это объясняет многое ... – user1878401

1

Это потому, что foo(A a) - это функция с точно такой же сигнатурой метода, поэтому она будет использовать ее.

В этом случае foo(B b) никогда не будет действительным вариантом, так как вам нужно будет сделать отражение, чтобы понять, что это может быть подходящий метод. Java не будет использовать отражение во всех параметрах только для того, чтобы увидеть, может ли метод в конечном итоге соответствовать, это будет просто слишком много времени.

Если вы хотите называть разные методы, то вы должны использовать наследование класса или другие полиморфные методы.

0

Вы должны иметь свои методы foo как методы экземпляра в классах A и B. то вызов в вашем случае x.foo() с экземпляром объекта B должен дать вам результат «B».

+0

OP сказал, что это не вариант –

0

Попробуйте

static class A { 
    public void foo() { 
     System.out.println("A"); 
    } 
} 

static class B extends A { 
    public void foo() { 
     System.out.println("B"); 
    } 
} 


public static void main(String[] args) { 
    A x = oracle(); 
    x.foo(); 
} 

функции-члены знать тип которых они являются членом.

+0

«[...], но я не могу ввести новую функцию-член для A и B» – Fildor

+0

Только то, писать :) +1 –

+0

ОП сказал, что это не вариант –

2

Эта статья дает хорошее объяснение того, что происходит: Overloading is compile-time binding

Я думаю, что вы собираетесь нужно сделать, это реализовать instanceof код в вас foo метод для лечения каждого типа по-разному.

Что касается вашего утверждения getClass().getName(), вы НИКОГДА не должны этого делать. Это то, для чего стоит instanceof. Работайте от более конкретных до менее конкретных (т.е. начинайте с B, затем A).

+0

Хорошо, я думаю, это хорошо отражает то, что многие здесь говорили. Если возможно, наличие функций-членов в 'A' и' B' будет более изящным, и в противном случае 'instanceof' будет единственным вариантом. – user1878401

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