2015-05-13 4 views
4

У меня есть 2 перегруженных метода, один из которых запускает суперкласс и тот, который выполняет подкласс. я ожидал бы, что при отправке подкласса java будет знать, как запустить метод, специфичный для подкласса. Увы, он запускает один из суперкласса. Вот пример:Как заставить java-методы запускать определенные реализации

public class Test { 

    static class SuperClass {} 

    static class SubClass extends SuperClass {} 

    static void stuff(SuperClass superclass) { 
     System.out.println("IN 1"); 
    } 

    static void stuff(SubClass subClass) { 
     System.out.println("IN 2"); 
    } 

    public static void main(String[] args) { 
     SuperClass aClass = new SubClass() ; 

     stuff(aClass) ; 
    } 
} 

Я бы ожидать "IN 2", чтобы быть напечатаны, но вместо этого я получаю "IN 1"

так у меня есть 2 вопроса: 1. Почему это происходит 2. Как достичь желаемого результата?

Заранее спасибо

+0

Подробная информация о том, как это работает: http://docs.oracle.com/javase/specs/jls/se7/html /jls-15.html#jls-15.12 –

ответ

10

Почему это происходит

Поскольку разрешение перегрузки происходит на время компиляции и тип времени компиляции переменной aClass является SuperClass

Как я достичь мой желаемый результат?

Либо изменить тип во время компиляции aClass в SubClass:

SubClass aClass = new SubClass(); 

Или ввергнуть в вызове метода:

stuff((SubClass) aClass); 

Если вы хотите фактически быть в состоянии справиться любой SuperClass, вы должны посмотреть на переопределение вместо , или visitor pattern/double dispatch.

+0

Или простой 'instanceof' может быть достаточно, в зависимости от ситуации, конечно. – immibis

2

Объявив aClass как экземпляр SubClass

SuperClass aClass = new SubClass() ; 

Даже если вы его экземпляр как SubClass, вы объявляете его в качестве суперкласса. Измените эту строку на:

SubClass aClass = new SubClass() ; 

и повторите попытку.

1

Как и мистер Скит, это происходит потому, что переменная времени компиляции aClass равна SuperClass. Вот пример использования interface и instanceof

public class Legit { 

    public static interface Animal {} 

    public static abstract class Mammal implements Animal {} 

    public static class Lion extends Mammal {} 

    public static class Cow extends Mammal {} 

    public static abstract class Reptile implements Animal {} 

    public static class Snake extends Reptile {} 

    public static void doSomething(Animal animal) { 
     if (animal instanceof Lion) { 
      System.out.println("RAAWWRR!"); 
     } else if (animal instanceof Cow) { 
      System.out.println("MOOO!"); 
     } else if (animal instanceof Reptile) { 
      System.out.println("HISSSSS!"); 
     } 
    } 

    public static void main (String ... args) { 
     Animal animal1 = new Lion(); 
     Animal animal2 = new Cow(); 
     Animal animal3 = new Snake(); 

     doSomething(animal1); 
     doSomething(animal2); 
     doSomething(animal3); 
    } 
} 

Выход:

RAAWWRR! 
MOOO! 
HISSSSS! 
Смежные вопросы