Zadzwoń super

Call super to zapach kodu lub antywzorzec niektórych obiektowych języków programowania. Call super to wzorzec projektowy, w którym określona klasa określa, że ​​w pochodnej podklasie użytkownik musi przesłonić metodę i wywołać samą przesłoniętą funkcję w określonym punkcie. Zastąpiona metoda może być celowo niekompletna i polegać na metodzie zastępującej w celu rozszerzenia jej funkcjonalności w określony sposób. Jednak fakt, że sam język może nie być w stanie wyegzekwować wszystkich warunków określonych w tym wywołaniu, sprawia, że ​​jest to antywzorzec.

Opis

W programowaniu obiektowym użytkownicy mogą dziedziczyć właściwości i zachowanie nadklasy w podklasach. Podklasa może przesłonić metody swojej nadklasy, zastępując własną implementację metody implementacją nadklasy. Czasami metoda nadrzędna całkowicie zastąpi odpowiadającą jej funkcjonalność w nadklasie, podczas gdy w innych przypadkach metoda nadklasy nadal musi być wywoływana z metody nadrzędnej. Dlatego większość języków programowania wymaga, aby metoda przesłaniająca jawnie wywołała metodę przesłoniętą w nadklasie, aby mogła zostać wykonana.

Wywołanie superantywzorca polega na tym, że użytkownicy interfejsu lub frameworka wyprowadzają podklasę z określonej klasy, przesłaniają określoną metodę i wymagają, aby nadpisana metoda wywołała oryginalną metodę z nadrzędnej metody:

The CallSuper anti-pattern

Jest to często wymagane, ponieważ nadklasa musi wykonać pewne zadania konfiguracyjne, aby klasa lub framework działały poprawnie, lub ponieważ główne zadanie nadklasy (które jest wykonywane tą metodą) jest tylko rozszerzane przez podklasę.

Antywzorzec jest wymogiem wywołania rodzica. Istnieje wiele przykładów w prawdziwym kodzie, w których metoda w podklasie może nadal wymagać funkcjonalności nadklasy, zwykle tam, gdzie tylko rozszerza funkcjonalność nadrzędną. Jeśli nadal musi wywoływać klasę nadrzędną, nawet jeśli w pełni zastępuje funkcjonalność, antywzorzec jest obecny.

Lepszym podejściem do rozwiązania tych problemów jest zamiast tego użycie wzorca metody szablonowej , gdzie nadklasa zawiera czysto abstrakcyjną metodę, która musi być zaimplementowana przez podklasy, a oryginalna metoda wywołuje tę metodę:

Avoiding the CallSuper anti-pattern

Odmiana językowa

Pojawienie się tego antywzorca w programach jest zwykle spowodowane tym, że niewiele języków programowania zapewnia funkcję zapewniającą umownie, że super metoda jest wywoływana z klasy pochodnej. Jednym z języków, który ma tę funkcję, w dość radykalny sposób, jest BETA . Funkcja ta występuje w ograniczony sposób na przykład w Javie i C++ , gdzie konstruktor klasy potomnej zawsze wywołuje konstruktora klasy nadrzędnej.

Języki obsługujące metody przed i po , takie jak Common Lisp (w szczególności Common Lisp Object System ), zapewniają inny sposób uniknięcia tego antywzorca. Programista podklasy może, zamiast przesłonić metodę klasy nadrzędnej, dostarczyć dodatkową metodę, która zostanie wykonana przed lub po metodzie klasy nadrzędnej. Ponadto programista nadklasy może określić przed , po i wokół , które gwarantują wykonanie oprócz działań podklasy.

Przykład

Załóżmy, że istnieje klasa do generowania raportu o inwentarzu wypożyczalni wideo. Każdy sklep ma inny sposób zestawienia aktualnie dostępnych filmów, ale algorytm generowania raportu końcowego jest taki sam dla wszystkich sklepów. Framework, który używa superantywzorca wywołania, może udostępniać następującą klasę abstrakcyjną (w C# ):

   
        
        
        
          
    
 abstract  class  ReportGenerator  {  public  virtual  Report  CreateReport  ()  {  // Wygeneruj ogólny obiekt raportu  // ...  zwróć  nowy  raport  (...);  }  } 

Oczekuje się, że użytkownik klasy zaimplementuje taką podklasę:

    
        
        
        

        
        
        
        
         
    
 class  ConcreteReportGenerator  :  ReportGenerator  {  public  override  Report  CreateReport  ()  {  // Zestawia dane w sposób charakterystyczny dla sklepu  // ...  // Projekt tej klasy wymaga wywołania funkcji nadrzędnej CreateReport() na  // końcu nadpisana funkcja. Należy jednak zauważyć, że ten wiersz można łatwo pominąć lub   // zwrócony raport można dalej modyfikować po wywołaniu, naruszając projekt klasy  // i być może także format raportu obejmujący całą firmę.  baza  zwrotna  .  Utwórz raport  ();  }  } 

Preferowany interfejs wygląda następująco:

   
       
        

        
        
          
    
 
       
 Klasa  abstrakcyjna  ReportGenerator  {  Public  Report  CreateReport  ()  {  Tabulate  ();  // Wygeneruj obiekt raportu ogólnego  // ...  zwróć  nowy  raport  (...);  }  chroniony  streszczenie  void  Tabulate  ();  } 

Implementacja zastąpiłaby tę klasę w następujący sposób:

    
        
        
        
    
 class  ConcreteReportGenerator  :  ReportGenerator  {  protected  override  void  Tabulate  ()  {  // Zestawianie danych w sposób charakterystyczny dla sklepu  // ...  }  } 
  1. ^ ab Fowler , Martin . "MF Bliki: CallSuper" .