2017-10-21 20 views
5

Na przykład mam klasę bazową procesora z metodą, która zwraca obiekt i bierze obiekt jako parametr. Chcę go rozszerzyć i utworzyć StringProcessor, który zwróci ciąg i przyjmie ciąg jako parametr. Jednak typowanie kowariantne jest dozwolone tylko z wartością zwracaną, ale nie z parametrem. Jaki jest powód takich ograniczeń?Dlaczego w nadpisywaniu metody java można mieć kowariantne typy zwracania, ale nie parametry kowariantne?

class Processor { 
    Object process (Object input) { 
     //create a copy of input, modify it and return it 
     return copy; 
    } 
} 

class StringProcessor extends Processor { 
    @Override 
    String process (String input) { // permitted for parameter. why? 
     //create a copy of input string, modify it and return it 
     return copy; 
    } 
} 

Odpowiedz

10

The Liskov principle. Projektując klasę Procesor, piszesz umowę mówiąc: "Procesor może wziąć dowolny obiekt jako argument i zwrócić obiekt".

The StringProcessor to procesor. Więc powinien przestrzegać tej umowy. Ale jeśli akceptuje String jako argument, narusza tę umowę. Pamiętaj: procesor powinien akceptować dowolny obiekt jako argument.

więc powinieneś być w stanie to zrobić:

StringProcessor sp = new StringProcessor(); 
Processor p = sp; // OK since a StringProcessor is a Processor 
p.process(new Integer(3456)); 

Po powrocie łańcuch, to nie narusza umowy: to powinien zwrócić obiekt, ciąg jest obiekt, więc wszystko jest w porządku.

Możesz robić, co chcesz osiągnąć z zastosowaniem leków generycznych:

class Processor<T> { 
    Object process (T input) { 
     //create a copy of input, modify it and return it 
     return copy; 
    } 
} 

class StringProcessor extends Processor<String> { 
    @Override 
    String process (String input) { 
     return copy; 
    } 
} 
0

Ponadto, jeśli chcesz to typ-teoretyczna odpowiedź, powodem tego jest to, rozważając stosunek Subtyping sprawie rodzajów funkcyjnymi związek jest kowariantna od typów powrotnych, kontrawariantny w rodzaju argumentu (np X -> Y jest podtypem U -> W jeśli Y jest podtypem W i U jest podtypem X).