views:

112

answers:

4

Does code in the constructor add to code in subclass constructors? Or does the subclass's constructor override the superclass? Given this example superclass constructor:

class Car{
     function Car(speed:int){ 
          trace("CAR speed "+speed)
     }
}

...and this subclass constructor:

class FordCar extends Car{
     function FordCar(model:string){ 
          trace("FORD model "+model)
     }
}

When an instance of FordCar is created, will this trace "Car" and "Ford" ??

Edit: Will arguments also add up? See updated code above.

+4  A: 

Yes, it will trace both. Usually your child class's constructors will have to call your base class's constructor. If more than one base class constructor is given, then you may have options. However, if only one is given, then you MUST satisfy its requirements.

Consider the following code and pay particular attention to the various constructors and how they work with the superclass's constructors:

public interface IAnimal
{
    string GetName();
    string Talk();
}

public abstract class AnimalBase : IAnimal
{
    private string _name;

    // Constructor #1
    protected AnimalBase(string name)
    {
        _name = name;
    }

    // Constructor #2
    protected AnimalBase(string name, bool isCutsey)
    {
        if (isCutsey)
        {
            // Change "Fluffy" into "Fluffy-poo"
            _name = name + "-poo";
        }
    }

    // GetName implemention from IAnimal.
    // In C#, "virtual" means "Let the child class override this if it wants to but is not required to"
    public virtual string GetName()
    {
        return _name;
    }

    // Talk "implementation" from IAnimal.
    // In C#, "abstract" means "require our child classes to override this and provide the implementation".
    // Since our base class forces child classes to provide the implementation, this takes care of the IAnimal implementation requirement.
    abstract public string Talk();
}

public class Dog : AnimalBase
{
    // This constructor simply passes on the name parameter to the base class's constructor.
    public Dog(string name)
        : base(name)
    {
    }

    // This constructor passes on both parameters to the base class's constructor.
    public Dog(string name, bool isCutsey)
        : base(name, isCutsey)
    {
    }

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal.
    public override string Talk()
    {
        return "Woof! Woof!";
    }
}

public class SmallDog : Dog
{
    private bool _isPurseDog;

    // This constructor is unique from all of the other constructors.
    // Rather than the second boolean representing the "isCutsey" property, it's entirely different.
    // It's entirely a coincidence that they're the same datatype - this is not important.
    // Notice that we're saying ALL SmallDogs are cutsey by passing a hardcoded true into the base class's (Dog) second parameter of the constructor.
    public SmallDog(string name, bool isPurseDog)
        : base(name, true)
    {
        _isPurseDog = isPurseDog;
    }

    // This tells us if the dog fits in a purse.
    public bool DoesThisDogFitInAPurse()
    {
        return _isPurseDog;
    }

    // Rather than using Dog's Talk() implementation, we're changing this because this special type of dog is different.
    public override string Talk()
    {
        return "Yip! Yip!";
    }
}

public class Chihuahua : SmallDog
{
    private int _hatSize;

    // We say that Chihuahua's always fit in a purse. Nothing else different about them, though.
    public Chihuahua(string name, int hatSize)
        : base(name, true)
    {
        _hatSize = hatSize;
    }

    // Of course all chihuahuas wear Mexican hats, so let's make sure we know its hat size!
    public int GetHatSize()
    {
        return _hatSize;
    }
}

public class Cat : AnimalBase
{
    // This constructor simply passes on the name parameter to the base class's constructor.
    public Cat(string name)
        : base(name)
    {
    }

    // This constructor passes on both parameters to the base class's constructor.
    public Cat(string name, bool isCutsey)
        : base(name, isCutsey)
    {
    }

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal.
    public override string Talk()
    {
        return "Meoooowwww...";
    }
}

public class Lion : Cat
{
    public Lion(string name)
        : base(name)
    {
    }

    // Rather than using Cat's Talk() implementation, we're changing this because this special type of cat is different.
    public override string Talk()
    {
        return "ROAR!!!!!!!!";
    }
}

[edit]

Your code that you added will usually not compile. The subclass's constructor usually MUST provide all parameters to the superclass's constructor. Not providing them is not an option. See my code to see how my subclass constructors provide the parameters to the superclass constructors. Sometimes they just pass on the parameters and other times they actually put hard-coded true/false values in.

Jaxidian
No, when an instance of the subclass is created, will it also execute code in the superclass?
Jenko
For constructors, yes, it will automatically execute both (you don't have an option here). For member methods, then the subclass must specifically reference the superclass's method.
Jaxidian
+5  A: 

Yes. In most languages, the base class constructor is executed, then the subclasses constructor. This will make it trace: "CAR", then "FORD".

Both class constructors should always execute if you construct an instance of the subclass. Depending on the language in question, the actual execution and choice of base class constructor, including ordering, may be different. (This is particularly true in languages which allow for multiple inheritance - as the order of execution can be difficult to determine at first glance in some cases.)


Edit:

In most languages, your edited code will not compile. The subclass typically needs to pass arguments of the same type to the base class constructors. This is language specific, but often looks something like:

function FordCar(model: string) : Car(42) {

In some languages (mainly dynamic languages), the language will try to automatically convert, but you often may still need to specify which of the parent constructors to call.

Often, you can do:

function FordCar(int: speed, model: string) : Car(speed) {
    trace("FORD model " + model)
}
Reed Copsey
I will always run? Meaning?
Jenko
@Jeremy: I reworded - better?
Reed Copsey
Yea! And will arguments also add up? Please see my updated code above.
Jenko
@Jeremy: I edited my answer to help more...
Reed Copsey
Thank you! Fantastic information.
Jenko
@Jeremy: Just remember that every language has its own rules for this - this is typically how it's done in nearly every OO language out there, but any specific language is free to define its own "rules"...
Reed Copsey
Is there a term for this? "constructor inheritance"? "constructor overriding"?
Jenko
@Jeremy: Typically, it's just part of inheritance, but sometimes, "constructor chaining" (though that's also used for chaining within the same class): http://java.about.com/od/c/g/constchaining.htm
Reed Copsey
+1  A: 

Constructors in C# (and most languages) are not inherited and cannot be overriden. However if the constructor does not explicitly call a base constructor an implicit call is made to the default constructor of the base class.

Mark Byers
This is language specific - but (in C#) also requires that the base class contains a default constructor. If there is no constructor without parameters, you'll get a compiler error.
Reed Copsey
+1  A: 

Just to confirm not all languages are alike: in Python, the default behaviour is the replacement of the superclass constructor.

class Car():
  def __init__(self, speed):
    print "speed", speed
    self.speed = speed
class FordCar(Car):
  def __init__(self, model):
    print "model", model
    self.speed = 180
    self.model = model

>>> FordCar("Mustang")
model Mustang

This is, imvho, sensible because Python allows multiple inheritance.

badp