Skip to content
Tags

33. Class inheritance in Codea

April 15, 2013

A recent forum post showed how to get one Codea class to “inherit” from another. In this post, I’ll explain

  • what that means
  • how to do it successfully
  • when you might use it

.
It mainly affects large, fairly complex projects, so you don’t need to read this if you like to keep things simple. But it is very interesting, very useful, and should deepen your understanding of classes.

What “inheritance” means (skip this part if you know already)

Suppose you are creating an RPG, and you have several types of dwarf, who share most of their behaviour but have some specific differences. You can program this in several ways

  • have one dwarf class with “if” tests to handle the differences
  • have one class for each dwarf, duplicating most of the code
  • have a generic dwarf class for the common behaviour, and a subclass for each type of dwarf

.
The first approach is the most obvious, but will start to get messy if there are than a few differences between dwarves. Your next thought is likely to be to duplicate and then modify the class for each dwarf, but then, every time you want to change something that affects all of them, you have to change several classes instead of one.

This is when the third approach becomes useful. You write a “base class” of dwarf containing all the code for the common behaviours. Base class is just a name – it is an ordinary class.

You then write another class for each of the specific dwarf types, which inherits all the code from the base class, and then adds more code to handle the specific differences between dwarves. So if you want to change any of the common code, you only have to do that in the base class, and it flows through to all the inheriting classes.

What does inheritance mean in practice?

If class B inherits from class A, that means that class B starts with a copy of all of class A’s code. Class B can then add more code to itself, and it can also change (“override”) the code it was given by class A.

But I’m sure all these words are starting to just swim around in your head – so let’s see an example.

Dwarf=class()

function Dwarf:init(n)
   Self.name=n --name
end

function Dwarf:Work()
  return self.name..' sings - Heigh ho, heigh ho, its off to work we go'
end

function Dwarf:DoMyThing()
    return self.name..' does nothing' -- default action
end

The Dwarf class provides a place for the name, a Work function that all dwarves will share, and a function DoMyThing that will be different for each dwarf.

We then create a class for each dwarf, based on the Dwarf class, and provide a name, and code for the DoMyThing function. So Dopey’s version might include this (omitting some of the code for simplicity):

function Dopey:DoMyThing()
     -- override, ie replace, the code in the Dwarf class
    return self.name..' sleeps'
end

So that each dwarf’s class will provide different behaviour for that function.

You can think of the base Dwarf class as a template for all the individual dwarfs. It provides all the common code, and includes all the functions you might need for a dwarf. The individual dwarf classes can then add or change the template code as required.

And that’s really all inheritance means – a bunch of classes sharing the same common code and function definitions. Like parent and child, and hence the name inheritance.

How to inherit classes in Codea

So let’s take the Dwarf class above, and create a class for Dopey that inherits it, and then personalises it.

-- First the Dwarf class -------
Dwarf=class()

function Dwarf:init(n)
   self:Settings(n) --see explanation below
end

function Dwarf:Settings(n)
    self.name=n
end

function Dwarf:Work()
  return self.name..' sings - Heigh ho, heigh ho, its off to work we go'
end

function Dwarf:DoMyThing()
    return self.name..' does nothing' -- default action
end

-- Now the Dopey class --------
Dopey=class(Dwarf) --inherits dwarf

function Dopey:init(n)
    self:Settings(n) --see explanation below
end

--no need to change work function at all
--so no code needed for it

function Dopey:DoMyThing()
    return self.name..' sleeps' -- customise this function
end

--now test that it works ------
function setup()
    d=Dopey('Dopey')
    print(d:Work())
    print(d:DoMyThing())
end

---Printout---
Dopey sings - Heigh ho, heigh ho, its off to work we go
Dopey sleeps

You can see from the above that once you have written the Dwarf class, the Dopey class is easy to write, just a couple of lines, because all the rest comes from Dwarf. I do need to explain one thing. Dwarf:init only had one line of code, setting the name – why have I moved it into a separate function called Settings?

The reason is that you will probably want an init function for the Dopey class, to do any special setup for Dopey. However, the Dwarf class also has an init function, to set the name. If you write an init function for Dopey, it will replace the Dwarf:init code, and so the name will not be set any more.

You will either have to copy the name setting code into Dopey:init (which brings back the original problem of having more than one copy of the same code), or else you have to somehow make the original a:init code run*, so that the name gets set. Please note that I’m assuming in a real project there would be much more than one line of code in a:init, so this would not be a small issue.
* you could do this from b:init with a.init(self,s) – note the dot, not a colon

For me, the simplest solution is take everything out of a:init, into another function I’ve called Settings, so there is only ever one line of code in Dwarf:init that needs to be replicated in Dopey:init.

And the final result is that it is very easy to create inheriting classes in Codea.

When would you use inheritance?

I’ve suggested in an earlier post that you would use classes where you have a number of similar objects that have individual properties (like position, for a set of balls, or breed, colour and age for a set of dogs). As long as those differences are just values – ie numbers or strings, such as name or age, an ordinary class is fine.

But if the differences require different code as well, and the “if” tests start getting messy, that’s when you might consider using inheritance.

Advertisement

From → Programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: