Kiedy tworzę własną niestandardową klasę Androida, tworzę extend
jej klasę natywną. Wtedy, kiedy chcę zastąpić metodę podstawową, zawsze wywołać super()
metodę, tak jak zawsze w onCreate
, onStop
itp
Pomyślałem, że to jest to, ponieważ od samego początku zespół Android doradzał nam, aby zawsze wywoływać super
nadpisanie każdej metody.
Ale w wielu książkach widzę, że programiści, bardziej doświadczeni ode mnie, często pomijają dzwonienie super
i naprawdę wątpię, czy robią to z braku wiedzy. Na przykład, spójrz na tego podstawowego SAX klasy parsera w których super
pominięto w startElement
, characters
i endElement
:
public class SAXParser extends DefaultHandler{
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
//do something
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}else () {
//do something
}
}
}
Jeśli spróbujesz utworzyć jakąkolwiek metodę nadpisywania za pośrednictwem Eclipse lub innego IDE, super
zawsze zostanie utworzona jako część zautomatyzowanego procesu.
To był tylko prosty przykład. Książki są pełne podobnego kodu .
Skąd wiedzą, kiedy musisz zadzwonić, super
a kiedy możesz pominąć dzwonienie?
PS. Nie wiąż się z tym konkretnym przykładem. To był tylko przykład losowo wybrany z wielu przykładów.
(To może brzmieć jak pytanie dla początkujących, ale jestem naprawdę zdezorientowany).
źródło
endElement
Dokument API mówi "Domyślnie nic nie rób. Twórcy aplikacji mogą przesłonić tę metodę ...", co oznacza, że możesz bezpiecznie wywołać super, ponieważ nie robi "nic", ale nie musisz i naprawdę możesz to zmienić. Często możesz stwierdzić, czy musisz / nie możesz / nie powinieneś tego robić, czytając dokumentację dotyczącą tej metody.Odpowiedzi:
Wywołując
super
metodę, nie zastępujesz zachowania metody, tylko ją rozszerzasz .Wywołanie
super
wykona dowolną logikę zdefiniowaną przez rozszerzaną klasę dla tej metody. Weź pod uwagę, że może to być ważny moment, w którym wywołaszsuper
implementację w swojej metodzie nadpisywania. Na przykład:Wywołanie do
B.save()
wykonasave()
logikę dla obuA
iB
, w tej określonej kolejności. Gdybyś nie dzwonił dosuper.save()
środkaB.save()
,A.save()
nie zostałbyś wezwany. A jeśli zadzwoniszsuper.save()
późniejsave(b)
,A.save()
zostanie skutecznie wykonany późniejB.save()
.Jeśli chcesz nadpisać
super
zachowanie (to znaczy całkowicie zignorować jego implementację i podać wszystko samodzielnie), nie powinieneś dzwonićsuper
.Na
SAXParser
przykład podasz, tym implementacje zDefaultHandler
tych metod są tylko pusty, dzięki czemu można je zastąpić podklasy i zapewnić zachowanie dla tych metod. W javadoc dla tej metody jest to również wskazane.O
super()
domyślnym wywołaniu w kodzie generowanym przez IDE, jak@barsju
wskazano w jego komentarzu, w każdym konstruktorze znajduje się niejawne wywołaniesuper()
(nawet jeśli nie piszesz go w swoim kodzie), co w tym kontekście oznacza wywołaniesuper
' domyślny konstruktor. PoIDE
prostu zapisuje go za Ciebie, ale zostanie również wywołany, jeśli go usuniesz. Zauważ również, że podczas implementacji konstruktorówsuper()
lub któregokolwiek z jego wariantów z argumentami (tj.super(x,y,z)
) Można wywołać tylko na samym początku metody.źródło
super()
(domyślny konstruktor superklasy) jest zawsze wywoływana, nawet jeśli jej nie określisz. Jeśli superklasa nie ma domyślnego konstruktora, pojawi się błąd kompilacji, jeśli nie wywołasz jawnie jednego z konstruktorów superklasy jako pierwszej instrukcji w konstruktorze podklasy.Zwykle, jeśli specjalna metoda API ma krytyczne znaczenie dla cyklu życia podstawowego kontekstu frameworka, zawsze będzie to wyraźnie określone i wyróżnione w dokumentacji API, podobnie jak w
Activity.onCreate()
dokumentacji API . Ponadto, jeśli interfejs API jest zgodny z solidnym projektem, powinien zgłosić pewne wyjątki, aby ostrzec dewelopera konsumenta w czasie kompilacji projektu i upewnić się, że nie wygeneruje błędu w czasie wykonywania.Jeśli nie jest to wyraźnie określone w dokumentacji API, wówczas deweloper-konsument może założyć, że wywołanie metody API nie jest obowiązkowe podczas jej zastępowania. Do dewelopera klienta należy decyzja, czy użyć domyślnego zachowania (wywołać
super
metodę), czy całkowicie je zastąpić.Jeśli warunek jest dozwolony (uwielbiam oprogramowanie typu open source), programista konsumencki zawsze może sprawdzić kod źródłowy API i zobaczyć, jak metoda jest faktycznie napisana pod maską. Sprawdź na przykład
Activity.onCreate()
źródło iDefaultHandler.startElement()
źródło .źródło
Test, który powinieneś zrobić w swojej głowie to:
„Czy chcę, aby cała funkcjonalność tej metody została wykonana za mnie, a potem coś zrobić?” Jeśli tak, to chcesz zadzwonić
super()
, a następnie dokończyć metodę. Odnosi się to do „ważnych” metod, takich jakonDraw()
, które obsługują wiele rzeczy w tle.Jeśli potrzebujesz tylko niektórych funkcji (jak w przypadku większości metod, które nadpisujesz), prawdopodobnie nie chcesz wywoływać
super()
.źródło
Cóż, Xavi udzielił lepszej odpowiedzi ... ale prawdopodobnie wiesz, co się
super()
dzieje, gdy wywoływana jest metoda z nadpisaniem ... reklamuje to, co zrobiłeś z domyślnym zachowaniem.na przykład:
metoda w klasie widoku, gdy jest zastępowana .. rysujesz coś przed powiedzeniem super.onDraw () pojawia się, gdy widok jest w pełni narysowany .. więc tutaj wywołanie
super
jest konieczne, ponieważ android ma kilka krytycznie ważnych rzeczy do zrobienia (np. onCreate ())ale w tym samym czasie
kiedy to nadpisujesz, nie chcesz wywoływać super, ponieważ pojawia się okno dialogowe z listą opcji dla EditText lub innego podobnego widoku .. To jest podstawowa różnica .. możesz zostawić to czasami .. ale dla inne metody, takie jak
onCreate() , onStop()
powinieneś pozwolić systemowi operacyjnemu obsłużyć.źródło
Nie otrzymałem jasno twojego pytania, ale jeśli pytasz, dlaczego nie wywołać
super
metody:Istnieje powód wywołania
super
metody: jeśli w klasie nadrzędnej nie ma konstruktora zeroargumentowego, nie jest możliwe utworzenie dla tego klasy potomnej, więc albo musisz zachować konstruktor bez argumentów w klasie nadrzędnej, albo potrzebujesz do zdefiniowaniasuper()
instrukcji wywołującejargument(how much argument constructor you have used in super class)
na początku konstruktora klasy potomnej.Mam nadzieję, że to pomoże. Jeśli nie, daj mi znać.
źródło
Zaimplementowałem listę tablic ograniczeń, taką jak
Jeśli spojrzysz na kod, po prostu wykonuje pewne wstępne sprawdzenie, zanim faktycznie pozwoli superklasie wykonać faktyczne dodanie elementu do listy. To mówi o jednym z dwóch powodów przesłaniania metody:
źródło
Dla tych, którzy również zastanawiali się, które zastąpione metody z Android Framework powinny wywołać
super
i znaleźli to pytanie - oto aktualna wskazówka z 2019 roku - Android Studio 3+ powie Ci, kiedy tego potrzebujesz .źródło