views:

46

answers:

2

Hellow, I've been working on OOP methods lately, and here is something I've always been wondering.

Let say we have the following situation. We have a collection of pets [dog, cat, mouse]. Each pet has the same behaviour: running, eating, sleeping. Furthermore, they all have a different visual representation.

Instead of making 3 seperated classes and recreate those 3 functions like this:

  • dog
  • eat function
  • run function
  • sleep function

[same goes for cat and mouse]

Is there a better way to simply "share" a collection of functions between these different classes, and somehow differ the behaviour of these function depening on the chosen class (the walking speed of a dog might be quicker than a cat, a cat might sleep more than a mouse etc).

I've looked at interfaces, but as far as I understood you can't actually code the functions, the interface just acts of a list of requirements that a class should have. Could be very wrong tho. Help is much appreciated :)

+1  A: 

Sounds like you just need inheritance?

class Animal {
    public function eat():void { stuff }
    public function run():void { stuff }
    public function sleep():void { stuff }
}

class Dog extends Animal {
}

...

I use this sort of thing all over my games.

To differ depending on the subclass:

If it's a big change, then obviously you should override the method in the subclass.

class Dog {
    public function wagTail():void { stuff }
    override public function run():void {
        super.run();
        wagTail();
    }
}

If it's a small change, you might choose to give the behaviour to the parent class and use member variables to alter it slightly:

class Animal {
    protected var walkSpeed:Number;
    public function walk():void {
        x += walkSpeed;
    }
}
class Dog {
    public function Dog() {
        walkSpeed = 6;
    }
}

Personally I never found interfaces terribly useful in AS3 -- every time I tried using them I ended up refactoring them later into classes instead, when I realised I wanted to share functionality between the implementations.

Chris Burt-Brown
This looks like it's heading the right way :) I could see myself getting stuck somewhere where a dog would need another set of function from another class though. As far as I know you can't extend 2 classes. But this seems sufficient for this example. Thanks!
Martino Wullems
Yeah, that's called multiple inheritance, and it's a pain to implement so barely any languages have it. ;) Usually you can put shared functionality in a parent class, but occasionally you have to go "against the grain" of OOP a little. For example you might be forced to give functionality to two child classes even though only one of them needs it. In this case you can try object composition (google it) -- which is never beautiful -- or you can fudge it a bit. Personally I would fudge it, but your mileage may vary. :)
Chris Burt-Brown
I was going to post an example with Dog, Beggar and a beg() function, but I think it might be too stupid for human consumption...
Chris Burt-Brown
A: 

As3 supports interfaces, try creating an interface for a mammal

package com.you.interfaces
{
public interface Mammal
{

    //--------------------------------------
    //  PUBLIC METHODS
    //--------------------------------------
    function eat():void;
    function move(speed:uint = 0):void;
    function sleep():void;

    //--------------------------------------
    //  GETTER/SETTERS
    //--------------------------------------
    function get health():uint;
    function set health(value:uint):void;
}
}

In a mammal implementation:

package com.you.animals
{
import com.philipbroadway.interfaces.Mammal;
import flash.display.Sprite;

public class Dog extends Sprite implements Mammal
{
    //--------------------------------------
    //  CONSTRUCTOR
    //--------------------------------------
    public function Dog()
    {
        super();
    }

    //--------------------------------------
    //  PRIVATE VARIABLES
    //--------------------------------------
    private var _hp:uint;
            private var _moveSpeed:uint;

    //--------------------------------------
    //  GETTER/SETTERS
    //--------------------------------------
    public function get health():uint
    {
        return 0;
    }

    public function set health(value:uint):void
    {
                   _hp = value;
    }
    //--------------------------------------
    //  PUBLIC METHODS
    //--------------------------------------
    public function eat():void
    {
                health++;
    }

    public function move(speed:uint=0):void
    {
                _moveSpeed++;
    }

    public function sleep():void
    {
                health++;
    }

}

}

Any of your other animals simply implement the Mammal class and all its methods. If you keep them abstract enough they should work across more animals. This allows you to manipulate a large assortment of animals knowing they all have a set of common methods expecting the same arguments, without creating an inheritance nightmare by just subclassing.

hope this helps. -philip

philip
The bit I don't understand about the use of interfaces, is that I would still need to recode the actual functionality of each mammel. Lets take your example on eating, I would still have to say that it would increase the health in each mammel class. Just being able to call "eat" (with optional parameters to alter the exact behaviour) which functionality is defined elsewhere seems much more efficient.I have a hard time explainint this. But thanks for the comment!
Martino Wullems
Its a preference in some ways and there are factors like the number of people working on the code base, the number of classes that need to use an interface and so on. [cont]..
philip
[cont] Interfaces make it easy for common objects to share a collection of shared methods that are internally implemented in a way that is specific to the object. In a graphics lib you might have a IShape interface that has a draw method which is then executed differently in each shape implementation (you would draw a circle different than a triangle) while still making it clear and easy to call a common draw() method on any class implementing the IShape interface.
philip