inheritancevalagenie

Class inheritance in Genie


Trying to understand class inheritance in Genie, I've created two classes (Kitten and Puppy) that are supposed to inherit properties from the Pet class. The aim is to ask minou to meow and duke to bark, however _name seems to be out of scope of the child classes. How to pass this property to the child classes?

Here is the code:

[indent=4]

// Experimenting with classes in Genie

class Pet

    _name:string

    construct ( name:string? )

        _name = name

class Kitten : Pet

    def meow()
        print self._name + " meowed!"

class Puppy : Pet

    def bark()
        print self._name + " barked!"

init
    var minou = new Kitten("Minou")
    var duke = new Puppy("Duke")

    minou.meow()
    duke.bark()

The error message is:

Test78.gs:16.15-16.24: error: Access to private member `Pet._name' denied
        print self._name + " meowed!"

Solution

  • There are a lot of tutorials on the Internet relating to inheritance and they often create complex hierarchies using animals or parts of vehicles. Conceptually these inheritance hierarchies are rigid and this is why it is often better to pass collaborating objects in the constructor (favouring composition over inheritance) and type checking the collaborators against an interface (polymorphism). This creates de-coupled objects and allows for greater flexibility, maintainability and testability in your program. So learn about inheritance, but also do so from a critical point of view.

    Genie does support sub-typing and inheritance. Your program encounters two problems. The first is scope and the second is passing parameters up the chain of constructors.

    First the problem of scope. The underscore in Genie signifies a class member is private. It can only be accessed by an instance of that class. To allow access to it from sub-types computer languages use the protected access modifier. This is not currently implemented in the Genie parser. See Bug 690848 - Add support for "protected" class members . So we have to make the name field public. This allows it to be accessed from sub-types, but also from any part of the program where an instance of Pet is in scope. In Genie we just remove the underscore to make it public.

    Once you have the scope working you will get an error "unable to chain up to base constructor requiring arguments". You will need to add constructors for your sub-types and these constructors need to set the name field. This can be done directly, e.g. name = pet_name, or by calling the constructor of the super-type with the correct argument, e.g. super( pet_name ). A working example showing both ways is below:

    [indent=4]
    init
        var minou = new Kitten( "Minou" )
        var duke = new Puppy( "Duke" )
        minou.meow()
        duke.bark()
    
    
    class Pet
        name:string
    
        construct( pet_name:string = "Anonymous" )
            name = pet_name
    
    
    class Kitten:Pet
        construct( pet_name:string = "Anonymous" )
            name = pet_name
    
        def meow()
            print name + " meowed!"
    
    
    class Puppy:Pet
        construct( pet_name:string = "Anonymous" )
            super( pet_name )
    
        def bark()
            print name + " barked!"