Start Info Community Spielen
 
 

Morgengrauner Dokumentation

Dateipfad: /home/mud/mudlib/doc//LPC/inheritance

KONZEPT
     inheritance

BESCHREIBUNG
     Mittels Vererbung kann man das Verhalten und/oder die implementierten
     Methoden eines Objektes in ein neues Objekt hineinerben.

     1. Wozu ist Vererbung gut
     1.1. Erben von Implementationen: Strukturieren von Bibliotheken
     Mit Vererbung der Implementation koennen aufeinander aufbauende und gut
     wart-/nutzbare Strukturen geschaffen werden:
     
     /std/thing/description beinhaltet
     - wie ein Objekt aussieht/welche Details es gibt
     - wie man das Objekt finden/identifizieren kann
     /std/thing/moving beinhaltet
     - wie man ein Objekt bewegen kann
     /std/thing erbt
     - /std/thing/description und
     - /std/thing/moving
     - damit den Code aus beiden Objekten (und noch andere)

     Sowohl thing/description als auch thing/moving sind nicht als
     eigenstaendige Objekte sinnvoll nutzbar, sind abstrakt.

     1.2. Erben von Schnittstellen und Verhalten      
     Durch das Erben von /std/thing werden Schnittstelle und auch
     Verhalten von /std/thing geerbt:
     
     -- keks.c --
     inherit "/std/thing";
     --
     
     Dadurch koennen jetzt andere Objekte, wie NPCs oder Spieler mit dem
     Keks-Objekt so interagieren, als wenn es ein /std/thing waere.

     Morgengrauen stellt eine grosse Bibliothek von miteinander sinnvoll
     agierenden Objekten unter /std zur Verfuegung, Die dort verfuegbaren
     Objekte sind groesstenteils selbsterklaerend, wie /std/npc,
     /std/armour oder /std/weapon.

     Das Keks-Objekt muss erweitert werden, wenn es sich vom normalen
     Ding unterscheiden soll. Typischerweise geschieht das durch
     Ueberschreiben der Initialisierungmethode namens "create". 
       
     2. Ueberschreiben/Erweitern von Verhalten/Methoden
     2.1. Ueberschreiben
     Um das Verhalten von geerbten Methoden zu erweitern, muss diese
     ueberschrieben werden:
     
     -- keks.c --
     ...
     void create() {
       SetProp(P_NAME, "Keks");
       SetProp(P_GENDER, MALE);
       AddId(({"keks"}));
     }
     --
     
     Allerdings wuerde jetzt der normale Code von "create" in /std/thing
     nicht mehr ausgefuehrt werden. Mit dem 'scope'-Operator :: wird
     innerhalb einer ueberschriebenen Methode auf deren bisherige
     Implementation zugegriffen:

     -- keks.c --
     ...
     void create() {
       ::create();
       SetProp(P_NAME, "Keks");
       SetProp(P_GENDER, MALE);
       AddId(({"keks"}));
     }
     --

     Auf geerbte globale Variablen kann normal zugegriffen werden, wenn 
     diese nicht vor direktem Zugriff durch erbende Objekte geschuetzt
     wurden. Also in ihrer Sichtbarkeit veraendert wurde.
     
     Ueberschreiben von Methoden in den davon erbenden Objekten kann durch
     das Schluesselwort 'nomask' verboten werden.

     2.2. Sichtbarkeit von Methoden und Variablen
     Es ist moeglich, Methoden und Variablen mit einem Modifikator fuer
     ihre Sichtbarkeit zu versehen, der auch bei der Vererbung zum
     Tragen kommt:
     - 'public' Methoden sind von aussen/innen in Eltern/Kind zugreifbar
     - 'protected' Methoden sind nur von innen in Eltern/Kind zugreifbar
     - 'private' Methoden sind nur von innen in Eltern zugreifbar
                 (also nur im definierenden Objekt selbst)   

     2.3 Laufzeit-Polymorphie (vielgestaltes Verhalten)
     Methoden werden in LPC immer erst zum Zeitpunkt ihres Aufrufs
     gebunden, also nicht schon beim Laden. Beispielsweise koennen
     wir unseren Keks essbar machen:

     -- keks.c --
     ...
     void create() {
       ...
       AddCmd("iss&@ID", "action_essen", "Was willst du essen?");
     }
     
     int action_essen() {
       if(this_player()->eat_food(1, 0, 
                                 "Du bekommst "+QueryPronoun(WEN)+
				 " nicht mehr hineingestopft.\n")>0) {
         write("Du isst "+name(WEN,1)+".\n");
         say(this_player()->Name(WER)+" isst "+name(WEN)+".\n");
         remove();
       }
       return 1;
     }
     --
     
     und jetzt in einem davon erbenden Kruemelkeks diesen beim Entfernen
     im "remove" kruemeln lassen:
     
     -- kruemelkeks.c --
     inherit "/doc/beispiele/inherit/keks.c";
     ...
     varargs int remove(int silent) {
       if(!silent && living(environment()))
         tell_object(environment(), Name(WER,1)+
	                            " kruemelt ein letztes Mal.\n");
       return ::remove(silent);
     }
     --
     
     Trotzdem wir "action_essen" nicht modifiziert haben, wird von dieser
     Methode in einem Kruemelkeks immer automatisch die aktuelle und
     kruemelende "remove" aufgerufen.

     3. Multiple Inheritance
     In LPC ist multiple Vererbung moeglich. Das heisst, man kann von 
     mehreren Objekten erben. Das kann zu Konflikten fuehren, zum Beispiel 
     wenn eine Methode in zwei Objekten von denen geerbt wurde vorkommt. 
     
     Diese Konflikte sollte man dann "per Hand" loesen in dem man diese 
     spezielle Methode ueberschreibt und mittels des scope-Operators die 
     gewuenschte(n) geerbt(en) Methode(n) aufruft:

     inherit "/std/weapon";
     inherit "/std/lightsource";

     void create() {
       weapon::create();
       lightsource::create();
       ...
     }

     void init() {
       weapon::init();
       lightsource::init();
       // oder sehr generell und unkontrolliert:
       // "*"::init();
     }

     Schwerwiegende Konflikte koennen auftreten, wenn eine gleichnamige
     Variable aus verschiedenen Objekten geerbt wird. Die Variablen
     existieren im letztlich erbenden Objekt zweimal und die verschiedenen
     geerbten Methoden greifen auf ihre jeweilige Variante zu.

     Beispiel ist die sog. "Masche" oder der "Diamond of Death": 

                        A    (Ursprungsobjekt mit globaler Variable x)   
                       / \
                      B   C  (B, C erben von A und manipulieren beide x)
                       \ /
                        D    (D erbt von B und A)

     Mit dem Schluesselwort 'virtual' kann die Doppelung beim Erben
     in B und C unterbunden werden.

SIEHE AUCH:
     inherit
     private, protected, public, nomask
     virtual
     objekte, oop
     /doc/beispiele/inherit


2.Feb 2008 Gloinson


zurück zur Übersicht

YOUTUBE | FACEBOOK | TWITTER | FEEDBACK | IMPRESSUM | DATENSCHUTZ 1992–2022 © MorgenGrauen.