On inheritance and polymorphism in cats and dogs (and other beasts too)

Adam D. Ruppe via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Dec 20 08:03:35 PST 2014


On Saturday, 20 December 2014 at 15:40:32 UTC, Derix wrote:
>   		// do what all beasts do

You'll want to call the function in the base class, which is done 
with the super keyword in D.

I wouldn't make the super function return the new instance 
though, that can't be as easily customized. I'd separate it into 
two functions: breed and genetic mix

class Beast {
      // call this on a new zygote
      // it is protected because it doesn't make sense to mix 
genetics
      // in public
      protected void mixGenetics(Beast mother, Beast father) {
           // modify this to be a combination of generic traits
           // for example
           this.furColor = mother.furColor + father.furColor;
      }
}


Now, make the specific breed functions on the subclasses. I 
didn't put that in the interface because you typically don't want 
to substitute parents with generic beasts - cats and dogs can't 
breed together, but if there was a breed(Beast) function in the 
base class, that would be permitted. (in OO theory, this is the 
liskov substitution principle)

class Cat : Beast {
     Cat breed(Cat sire) {
        Cat offspring = new Cat();
        offspring.mixGenetics(this, sire);
        return offspring;
     }

    protected override void mixGenetics(Cat mother, Cat father) {
        super(mother, father); // calls the generic 
Beast.mixGenetics
        // now we can do cat-specific stuff
        this.pickiness = mother.pickiness * father.pickiness;
    }
}


Dog would look similar to cat.



However, since mixGenetics really only makes sense when making a 
new Cat, you might want to make it a constructor instead of a 
method, then follow the same pattern.

> Cat class. How do I de-specialize it so it can behave as an
> instance of the more generic Beast class ? Then, the offspring
> will in turn be an instance of Beast : how to cast it as a Cat ?

Generally speaking, de-specialization happens automatically. The 
super keyword calls the parent class' version which takes care of 
all that.

You can cast Beasts back into Cats with cast(Cat) beast. Be sure 
to check for null - if beast is a dog, that cast will return null.

> So far, all I've been able to do is to dance around the issue by
> writting ad-hoc constructors like

that makes some sense, you'd just want to make sure the specific 
ones are done in specific child constructors, then call the 
parent with super()


More information about the Digitalmars-d-learn mailing list