Felfelé hívás
A felfelé hívás az objektumorientált programozás antimintája. Ebben a szülő osztály egy metódusát a gyermek osztálynak felül kell definiálnia, azonban annak meg kell hívnia azt a metódust, amit éppen felüldefiniál.
A felülírt metódus nem teljes, és a gyermek osztálynak egy előírt módon ki kell bővítenie a funkcionalitását. Azonban nem biztos, hogy kikényszeríthető a szülő osztály metódusának előfeltétele a gyermek osztályban felüldefiniálás közben. Emiatt antimintának tekintik, és a sablon metódust javasolják helyette.
Leírás
[szerkesztés]Az objektumorientált programozásban egy osztály örökölheti szülője tulajdonságait és viselkedését. A metódusokat felül is írhatja, ezzel saját megvalósítást adva. Ez vagy teljesen helyettesíti a szülő osztály metódusát, vagy meghívja azt is. A legtöbb programozási nyelvben ezt explicit kell megtenni.
A felfelé hívásban egy interfész vagy keretrendszer megköveteli, hogy a felhasználó származtasson egy osztályból, írja felül az adott metódust, és hívja meg a szülő osztály metódusát.[1]
Erre azért van szükség, mivel a szülő metódus végzi el az inicializálást, vagy a gyermek osztály csak kibővíti a szülő funkcionalitását.
Meg kell jegyeznünk, hogy a kötelezővé tétel az antiminta. Sok példa van valós kódban, amikor a gyermek osztály csak ki akarja bővíteni a szülő működését. Ha még akkor is meg kell hívnia a szülő metódusát, ha azt teljesen egy új viselkedéssel akarja helyettesíteni, akkor antimintához jutunk.
Ehelyett javasolt a sablon metódus, amikor a szülő osztályban egy metódus bizonyos pontokon meghív tisztán absztrakt metódusokat, amelyek megvalósítását a gyermek osztályokra hagyja.[1]
Különböző nyelvi megoldások
[szerkesztés]A felfelé hívás antimintája azért van jelen, mivel csak kevés nyelvben van olyan lehetőség, ami szerződésben biztosítja, hogy a szülő metódusa meghívódjon. A BETA radikálisan bevezette ezt a lehetőséget. Konstruktorokra több nyelv, a Java és a C++ is használja, a gyermek osztály konstruktorának először meg kell hívnia a szülő konstruktorát az örökölt tagok inicializálására, majd utána csinálhat bármit is.
Az antiminta megoldható az aspektusorientált programozásból eredő before és after, néha around is metódusok definiálásával, ahogy azt a Common Lisp CLOS rendszere is felajánlja. A gyermek osztály ezeket külön felülírhatja, és a rendszer garantálja, hogy ezek végrehajtódnak a szülő metódus előtt, után, vagy körül.
Példák
[szerkesztés]Legyen egy osztály, ami egy videokölcsönző készletéről készít jelentést! Minden egyes kölcsönzőnek más az éppen elérhető készlete, de a jelentést készítő algoritmus ugyanaz. A felfelé hívást használó keretrendszer a következő absztrakt osztályt nyújtja C Sharp nyelven:
abstract class ReportGenerator {
public virtual Report CreateReport() {
// Generate the general report object
// ...
return new Report(...);
}
}
A felhasználónak ehhez hasonlóan kell megvalósítani a gyermek osztályt:
class ConcreteReportGenerator : ReportGenerator {
public override Report CreateReport() {
// Tabulate data in the store-specific way
// ...
// Design of this class requires the parent CreateReport() function to be called at the
// end of the overridden function. But note this line could easily be left out, or the
// returned report could be further modified after the call, violating the class design
// and possibly also the company-wide report format.
return base.CreateReport();
}
}
Sablon metódussal az absztrakt osztály:
abstract class ReportGenerator {
public Report CreateReport() {
Tabulate();
// Generate the general report object
// ...
return new Report(...);
}
protected abstract void Tabulate();
}
A gyermek osztály:
class ConcreteReportGenerator : ReportGenerator {
protected override void Tabulate() {
// Tabulate data in the store-specific way
// ...
}
}
Jegyzetek
[szerkesztés]Fordítás
[szerkesztés]Ez a szócikk részben vagy egészben a Call super című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.