2013-02-23 11 views
6

Próbuję wprowadzić i zastąpić metodę z różnymi typami zwracania, bez konieczności wymuszania oddawania typu.Różne metody zwracania metody abstrakcyjnej w języku Java bez odlewania

public abstract class A { 
public abstract Object getValue(String content); 
} 

public class B extends A { 
public String getValue(String content) {...} 
} 

public class C extends A { 
public int getValue(String content) {...} 
} 


public class D extends A { 
public boolean getValue(String content) {...} 
} 

// Main loop: 
for (A a : allAs) 
{ 
// I want to use the method getValue() and corresponding to the type return a String, int or boolean without casting the return type 
} 

Moje pytanie: Czy to możliwe, aby powrócić różne typy bez zmuszania do oddania? Jak wygląda abstrakcyjna metoda rozwiązania problemu?

myślę, że musi być rozwiązaniem, ponieważ kompilator powinien znać typ zwracany ...

+0

Nie można przesłonić na podstawie typów zwracanych. –

+0

I ten program nie skompiluje się. –

Odpowiedz

13

W twoim przykładzie, klasy C i D nie zostaną skompilowane. Zastąpione metody w nich naruszają Liskov substitution principle, a ich typ zwrotu jest niekompatybilny z ich rodzica. To, czego szukasz, można osiągnąć przy pomocy leków generycznych, o ile chcesz zrezygnować z używania prymitywów jako typu zwrotu.

abstract class A<T> { 
    public abstract T getValue(String content); 
} 

class B extends A<String> { 
    public String getValue(String content) { } 
} 

class C extends A<Integer> { 
    public Integer getValue(String content) { } 
} 

class D extends A<Boolean> { 
    public Boolean getValue(String content) { } 
} 
+0

Dzięki. Ten kod może działać. Jednak zwracany typ getValue() jest "Obiektem", więc muszę go rzucić. – erwingun2010

+0

@ erwingun2010 Jeśli twoja metoda ma zwracany typ 'Object', możesz być przyczyną wystąpienia błędnej klasy. Zrób to: 'A bInstance = new B();' Jeśli nie dodasz typu do deklaracji A, twoje abstrakcyjne metody zwrócą 'Object'. – fiskeben

3

co opisujesz nie jest możliwe w ogóle. Jeśli jednak podklasa zwróci "węższy" podtyp powrotu metody nadklasy, jest to nazywane "kowariantnym typem zwracania" i jest dozwolone w Javie od czasu JDK 1.5. Jednak na podstawie twojego przykładu nie sądzę, że powrót do kowariancji jest tym, czego szukasz.

Zakładam, co chcesz, to

for (A a : allAs) 
{ 
    String b = a.getValue(); 
    int c = a.getValue(); 
} 

Problemem tutaj jest, oczywiście, że kompilator nie ma możliwości dowiedzenia się, w czasie kompilacji, która z tych dwóch stwierdzeń jest poprawne, a oni nie mogą jednocześnie być poprawne.

+0

Dokładnie tego chcę. Wciąż nie rozumiem, dlaczego kompilator nie wie w czasie kompilacji, który typ zwracania jest poprawny. Podczas inicjowania allAs używam => allAs.add (new B()); allAs.add (nowy C()); – erwingun2010

+0

W pokazanej przeze mnie próbce, obie instrukcje w pętli odnoszą się do _ jedynej instancji 'A', która jednocześnie nie może być jednocześnie" B "i" C ". W jaki sposób kompilator powinien wiedzieć, co to jest, skoro tak się nie dzieje, dopóki nie zostanie uruchomiony? –

0

W przykładzie definicja class B jest ok, ponieważ String jest podklasą Object. Pozostałe dwa nie będą się kompilować, ponieważ są to typy pierwotne. Można jednak zastąpić je wartościami Integer i Boolean, aby rozwiązać ten problem.

Jeśli chodzi o główną pętlę, jeśli przeglądasz je jako odniesienia do A, będziesz mógł korzystać tylko z definicji metody A, która zwraca Object.

2

Można użyć generycznych.

public abstract class A<T> { 
    public abstract T getValue(String content); 
} 

public class B extends A<String> { 
    public String getValue(String content) {...} 
} 

itd ... int nie działa jako typ zwrotu, ale liczba całkowita byłaby.

nie jestem wpisując w kompilator, więc nie może być literówki ...

Jak zauważył Jim i Chris, jeśli jesteś zapętlenie nad Jak można dostać tylko „A” wynik, który jest Obiekt.

+0

Dzięki. Na pewno muszę użyć prymitywów String, Boolean, Integer, .... – erwingun2010

Powiązane problemy