2012-04-20 7 views
101

Kiedy tworzę własną niestandardową klasę Androida, I extend to jej rodzima klasa. Wtedy, kiedy chcę zastąpić metodę podstawową, zawsze zadzwonić super() metody, tak jak ja zawsze w onCreate, onStop itpKiedy NIE wywoływać metody super() podczas przesłonięcia?

A myślałem, że to jest to, co od samego początku Androida zespół poradził nam zawsze zadzwoń pod numer super w przypadku każdego nadpisania metody.

Ale w wielu książek widzę, że deweloperzy, bardziej doświadczeni ode mnie, często należy pominąć powołanie super i wątpię, robią to jako brak wiedzy. Na przykład, spójrz na tej podstawowej klasy SAX parsera gdzie 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 próbujesz stworzyć dowolną metodę obejścia poprzez Eclipse lub innego IDE, super zawsze będzie tworzona jako część zautomatyzowanego procesu.

To był tylko prosty przykład. Książki są pełne podobnego kodu.

Jak oni wiedzieć, kiedy należy zadzwonić super i kiedy można pominąć to dzwoni?

PS. Nie wiąż do tego konkretnego przykładu. Był to tylko przykład losowo wybrany z wielu przykładów.

(To może brzmieć jak początkujący pytanie, ale jestem naprawdę mylić.)

+3

"Dokument API endElement's mówi:" Domyślnie nic nie rób, autorzy aplikacji mogą zastąpić tę metodę ... "oznacza, że ​​możesz bezpiecznie zadzwonić super, ponieważ nie" nic ", ale nie musisz i naprawdę możesz to zmienić. Często możesz stwierdzić, czy musisz/możesz/nie powinieneś tego robić, jeśli czytasz dokument dotyczący tej metody. – zapl

+1

Mały przykład: Używam onBackPressed() na ekranie powitalnym i NIE Wzywam super, więc nie wychodzi z plusku, po prostu wyłącza przycisk. –

+0

@sandalone Przepraszamy za pytanie, ale czy masz jakieś doświadczenie w zakresie obsługi podatku VAT w rozliczeniach w ramach aplikacji i które kraje są wykonywane automatycznie przez Google i które muszę ręcznie zgłosić/zapłacić podatek VAT? zobacz http://stackoverflow.com/questions/36506835/android-in-app-billing-vat-tax –

Odpowiedz

130

przez wywołanie metody super, nie jesteś nadrzędnymi zachowanie metody, jesteś to rozszerzenie .

Wywołanie super wykona żadnej logiki klasa jesteś rozszerzającego zdefiniowany dla tej metody. Weź pod uwagę, że może to być ważne w momencie, gdy zadzwonisz pod implementację super w nadpisanie metody. Na przykład:

public class A { 
    public void save() { 
     // Perform save logic 
    } 
} 

public class B extends A { 
    private Object b; 
    @Override 
    public void save() { 
     super.save(); // Performs the save logic for A 
     save(b); // Perform additional save logic 
    } 
} 

Wywołanie B.save() wykona save() logikę zarówno A i B, w tym konkretnym celu. Jeśli nie dzwonisz pod numer super.save(), to w nim nie będzie wywoływana funkcja B.save(), . A jeśli zadzwonisz super.save() po save(b), A.save() będzie skutecznie wykonywane później B.save().

Jeśli chcesz ręcznymsuper „s zachowanie (czyli całkowicie zignorować jego wdrożenia i zapewnienia sobie to wszystko), nie powinno być wywołanie super.

W podanym przez Ciebie przykładzie dla tych metod jest implementations z DefaultHandler tylko puste, tak aby podklasy mogą nadpisać je i zapewnić zachowanie dla tych metod. W metodzie javadoc dla tej metody jest to również wskazane.

public void startElement (String uri, String localName, 
    String qName, Attributes attributes) throws SAXException { 
    // no op 
} 

O zaproszeniu super() domyślnego w kodzie generowanym przez IDE, jak @barsju wskazał w swoim komentarzu, w każdym konstruktora istnieje niejawna wywołanie super() (nawet jeśli nie pisać go w kodzie), który oznacza w tym kontekście wywołanie domyślnego konstruktora super. IDE po prostu zapisuje go dla ciebie, ale zostanie również wywołany, jeśli go usuniesz. Zauważ również, że podczas implementacji konstruktorów, super() lub którykolwiek z jego wariantów z argumentami (tj. super(x,y,z)) można nazywać tylko na samym początku metody.

+14

Nie zanotuj, że dla konstruktorów 'super()' (domyślny konstruktor super klasy) jest zawsze wywoływany, nawet jeśli go nie określisz. Jeśli super klasa nie ma domyślnego konstruktora, otrzymasz błąd kompilacji, jeśli nie wywołasz jednoznacznie jednego z konstruktorów super klasy jako pierwszej instrukcji w konstruktorze podklasy. – barsju

+1

Tak, to po prostu lenistwo - dla metod, które znamy, nie rób niczego, po prostu pomiń to dla zwięzłości. – Voo

+1

Dzięki za cenne uwagi, @barjsu, uwzględniłem te szczegóły w odpowiedzi. –

3

Dobrze Xavi dał lepszą odpowiedź .. ale prawdopodobnie może być wiedząc, co ma zrobić, gdy nazywa super() w zastąpiona metoda reklamy ... to co zrobiliście z domyślnym zachowaniem ..

np :

onDraw() 

metoda w klasie widoku kiedy zamienione na .. narysować coś przed mówiąc super.onDraw() wydaje się, gdy widok jest całkowicie wyciągnąć .. więc o wywołanie super jest konieczne, ponieważ android ma pewne krytycznie ważne rzeczy do (jak onCreate())

ale jednocześnie

onLongClick() 

kiedy przesłonić tego, że nie chcesz, aby wywołanie super, ponieważ powoduje wyświetlenie okna dialogowego z listą opcji dla EditText lub innego podobnego widoku .. Ów podstawowy diff .. masz możliwość zostawić go kilka razy .. ale dla innych metod, takich jak onCreate() , onStop() powinieneś pozwolić OS obsłużyć to ..

2

Nie dostałem twojego pytania wyraźnie, ale jeśli pytasz o to dlaczego nie wywoływanie metody super:

Istnieje powód, aby wywoływać metodę super: jeśli nie ma konstruktora argumentów zerowych w klasie nadrzędnej, nie można utworzyć klasy potomnej dla tej klasy, więc albo zachowaj konstruktor bez argumentów w klasie nadrzędnej, albo musisz zdefiniować instrukcję wywołania super() z argument(how much argument constructor you have used in super class) u góry konstruktora klasy potomnej.

Mam nadzieję, że to pomoże. Jeśli nie, daj mi znać.

7

Badanie należy zrobić w twojej głowie jest:

„Czy chcę wszystkich funkcjonalności tej metody dla mnie zrobił, a potem coś zrobić potem?” Jeśli tak, to chcesz zadzwonić pod numer super(), a następnie zakończyć metodę. Dotyczy to "ważnych" metod, takich jak onDraw(), które obsługują wiele rzeczy w tle.

Jeśli potrzebujesz tylko niektórych funkcji (jak w przypadku większości metod, które zastąpisz), prawdopodobnie nie chcesz dzwonić pod numer super().

15

Skąd wiadomo, kiedy należy zadzwonić super i kiedy można pominąć wywoływanie?

Zazwyczaj, jeśli specjalna metoda API ma krytyczne znaczenie dla bazowego cyklu życiowego kontekstu ramy, to zawsze będzie wyraźnie stwierdził i podkreślił w dokumentacji API, jak Activity.onCreate() API documentation. Co więcej, jeśli interfejs API jest zgodny z solidną konstrukcją, powinien on zgłaszać pewne wyjątki, aby powiadomić dewelopera-konsumenta podczas 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, to jest całkiem bezpieczne dla dewelopera konsumenta założenie, że metoda API nie jest obowiązkowa do wywołania podczas jej przesłonięcia. Od dewelopera do konsumenta zależy, czy zastosować domyślne zachowanie (wywołanie metody super), czy też całkowicie je zastąpić.

Jeśli warunek jest dozwolony (uwielbiam oprogramowanie z otwartym kodem źródłowym), programista konsumencki zawsze może sprawdzić kod źródłowy API i zobaczyć, jak ta metoda jest faktycznie napisana pod maską. Sprawdź na przykład Activity.onCreate() source i DefaultHandler.startElement() source.

+0

Dziękuję za wyjaśnienie mi dodatkowych rzeczy. Dziękuję za przypomnienie, że sprawdzam kod źródłowy. – sandalone

2

I wdrożone ograniczenie listy tablicy jak

public class ConstraintArrayList<T> extends ArrayList<T> { 
    ConstraintArrayList(Constraint<T> cons) {this.cons = cons;} 
    @Override 
    public boolean add(T element) { 
    if (cons.accept(element)) 
     return super.add(element); 
    return false; 
    } 
} 

Jeśli spojrzeć na kod, to po prostu ma jakiś pre-checking zanim faktycznie pozwalając super klasy wykonać rzeczywiste dodanie elementu do listy. Mówi jeden z dwukrotnych powodów metoda nadrzędnego:

  1. Extensibility gdzie chcesz przedłużyć co super klasa może zrobić
  2. Specyfika gdzie chcesz dodać specyficzne zachowanie przez polimorfizm takie jak we wspólnym Animal królestwo przykład semantyki ruchu, w którym sposób poruszania się ptaków (latanie) i poruszania żab (chmiel) jest specyficzny dla każdej klasy podrzędnej.