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!"
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!"