Dokumentation zu: inheritance(C)

HR Image


        Have you noticed how many objects in the system have the same
        functionality in common? Let's look at rooms for instance, they
        all have the ability to host people and provide commands. It's
        not that every room is programmed with the same basic functions
        again and again, rather it will use a model room and then make
        some special changes to it. That doesn't work by copying the
        file.. Ouch! Don't replicate code! But by putting a tiny inherit

                inherit "<model-class>";

        at the beginning of your new file. This must come before any local
        variables or functions. Once inherited your class will behave just
        like the model class, because all the public methods are available
        to the outside world. Now it is in your hands to change such an
        inherited behaviour. You have the following tools to do so:

        * Access to variables

        It is one of the best design decisions in LPC that variables
        are not accessible from outside, but you can use inherited
        variables just as if they were your own. Modifiers apply however.

        * Method overloading

                int method_that_also_exists_in_the_model() {
                        <your new code>

        You can simply rewrite a method that is also defined in the model
        class, and thus change how it behaves. Contrary to other languages
        in LPC method overloading only matches the name of the method, so
        even by changing the amount and type of parameters you will mask
        out the original version of the method. You can even apply other
        modifiers to it as the original.

        * Calling inherited methods

                int method_that_also_exists_in_the_model() {
                        <your new code>
                        return ::method_that_also_exists_in_the_model();

        You can add to the behaviour of a method by redefining it,
        then calling it from within your new version. You can actually
        call inherited methods from anywhere in your code. The double
        colon tells the compiler you are looking for the inherited

        Let's imagine very simple food in a file called "/the/food.c":

                // unless "modified" variables are accessible by inheritors
                int vitamins = 10;

                // please overload this function with your own description
                public short() { return "something edible"; }

                // let's do some standard action for food
                public consume() {
                        this_player() -> nourish(vitamins);

        And now someone else decides to do some italian cooking in a
        file called "/the/fusilli.c"

                inherit "/the/food";

                // we have our own variables.
                int gone_cold = 0;

                // and we simply redefine the short() function to replace it
                public short() {
                    // description changes depending on gone_cold
                    return "a "+( gone_cold ? "stinking" : "steaming" )
                            +" plate of fusilli";

                // we have a new function to make food go cold
                private deteriorate() {
                    gone_cold = 1;
                    write("The fusilli have gone cold.\n");

                // assume this gets called at creation
                private create() {
                    // we can access the variable we inherited from food.c
                    vitamins = 44;           // tomato has plenty of vitamins

                    // go cold in 5 minutes
                    call_out( #'deteriorate, 5 * 60 );

                // we can overload the function even with new parameters
                public consume(how) {
                    // fetch the name of the person, or use "Someone"
                    string name = this_player() -> name() || "Someone";

                    if (!gone_cold) {
                        write("You enjoy a delicious plate of fusilli.\n");
                        say(name +" guzzles a plate of hot fusilli.\n");
                    else if (how == "quickly") {
                        write("You eat the fusilli so quickly you "
                              "hardly notice they have gone cold.\n");
                        say(name +" wolfs down a plate of cold fusilli.\n");
                    else {
                        write("You eye the plate and wonder if you "
                              "really feel like eating cold fusilli.\n");
                        return; // don't eat

                    // and here comes the most important part:
                    // we execute consume() from food.c, so we
                    // actually inherit its behaviour.

        * Doing multiple inheritance

        While the Java(TM) language has so-called interfaces as a kludge,
        LPC doesn't need them as it supports real multiple inheritance.
        A very powerful feature, it lets you combine the behaviour of
        several classes into a new one. Simply put several lines of
        inherit declarations underneath each other. If you have name
        collisions in the namespace of inherited methods, you will have
        to address them explicitely with a "the/file"::method(args) syntax.

        * Wildcarded multiple inheritance

        LDMud 3.2.1@117 introduces an advanced voodoo syntax which allows
        you to call several methods in model classes at once. This works by
        writing a glob type match ('*' and '?' wildcards) into the string
        in front of the double colon, as in "*"::create().
        I wouldn't recommend you to use this, it's better to be clearly
        conscious of what you inherit and do. But if you're desperate, there
        you go.

        Since LDMud 3.5.0 it is possible to pass arguments as well.

        * Duplicate functions

        When functions with the same name are inherited multiple times
        (via multiple inheritance), the compiler chooses a dominant
        definition that will finally be visible.

        When both functions come from the same inherit that is inherited
        virtually, then (and only then) they are considered the same
        function. If this is not the case then the compiler chooses as
        following (former rules have precedence over later rules):
         1. Private definitions are ignored.
         2. Nomask definitions have precedence.
         3. The first inherited function has precedence.

        The following table shows the result of these rules (if a function
        is private and nomask, it is considered private here):

        First       |      Second inherited function
        inherited   |
        function    |   private    |    nomask    |     other
        private     |    none      |    second    |    second
        nomask      |    first     |    error     |    first
        other       |    first     |    second    |    first

          inherit "foo";
          inherit "bar";
          inherit "baz";
          inherit "ball";

          reset() {
                // calls bar::reset() and baz::reset()

                // calls bar::reset(), baz::reset() and ball::reset()

                // calls every inherited reset() function.

                "ball"::rejoice("Listen to italectro today!");
                // only explicit filename of model class allows
                // passing arguments to the inherited method

        symlynX of PSYC and Nemesis, with a little help from Someone

        functions(LPC), initialisation(LPC), modifiers(LPC), pragma(LPC),
        function_exists(E), functionlist(E), inherit_list(E),
        symbol_variable(E), variable_exists(E), variable_list(E)

Start » Magierhandbuch » Docu » Concepts » Inheritance Letzte Generierung: 25.04.2021, 01:58
Email an:
Valid HTML 4.01!