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

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Dec 21 17:22:50 PST 2014


On 12/22/2014 1:11 AM, Derix wrote:
>
> Yep, I rekon the difference was not clear to me. It still isn't
> right now, but at least now I know that it exists and I have to
> look into it.

Overriding - a subclass reimplements a method from a base class. The 
method must have the same number and type of parameters. The subclass 
version essentially replaces the superclass version.

import std.stdio;

class A
{
    public void foo( int x )
    {
       writeln( "I'm an A." );
    }
}

class B : A
{
    // Note that the parameter is an int,
    // just as in the base class
    public override void foo( int x )
    {
       writeln( "I'm a B." );
    }
}

void main()
{
     // prints "I'm an A."
     A one = new A;
     one.foo();

     // prints "I'm a B."
     A two = new B;
     two.foo();

     // ditto
     B three = new B;
     three.foo();
}

Overloading - two or more methods with the same name, but different 
types and/or number of parameters. They can be implemented in a single 
class, or in a subclass. Which method is called depends on the 
parameters passed at the call site.

import std.stdio;

class A
{
     void bar( int x )
     {
        writeln( "One int." );
     }

     void bar( double x )
     {
        writeln( "One double." );
     }
}

class B
{
     void bar( int x, double y )
     {
    	writeln( "An int and a double." );
     }

}

void main()
{
     A one = new A;

     // prints "One int."
     one.bar( 10 );

     // prints "One double."
     one.bar( 10.0 );

     // Error -- one is declared as an A.
     // A does not have the int,double version.
     one.bar( 10, 10.0 );

     A two = new B;

     // prints "One int."
     two.bar( 10 );

     // prints "One double."
     two.bar( 10.0 );

     // Error -- the underlying instance of two
     // is a B, but two is declared as an A. A
     // does not have the int,double version
     two.bar( 10, 10.0 );

     B three = new B;

     // prints "One int."
     three.bar( 10 );

     // prints "One double."
     three.bar( 10.0 );

     // prints "An int and a double."
     three.bar( 10, 10.0 );	
}

>
> As to the spell you cast to my cats in your rewriting of the
> class, I'm still a bit confused about the ways of the 'downcast'.
> I'll try and compile a working hack around your outline, but that
> will have to wait another day : late Sunday afternoon, lazy ...

Using the A and B classes from above:

class C : A {}

void main()
{
    A one = new A;

    // This cannot work. One is not a B,
    // and cannot be 'downcast' to be. The line
    // 'new A' means it is and always will be
    // an A.
    B aB = cast( B )one.
    assert( aB is null );

    A two = new B;

    // This works. Since two was assigned a B, the
    // compiler knows that it can be 'downcast' so
    // it lets you do it.
    B anotherB = cast( B )two;
    assert( anotherB !is null );

    A three = new C;

    // Again, this cannot work. This instance was created
    // as a C, not a B, so the cast will result in null.
    B yaB = cast( B )three;
    assert( yaB is null );

    // It *can* be cast to a C
    C aC = cast( C )three;
    assert( aC !is null );


    // And instances of B and C can be 'upcast' to A
    A four = cast( A )anotherB;
    A five = cast( A )aC;
}

downcasting - taking an instance of a class and casting it to a 
subclass. This can only work if the instance was originally created as a 
that specific subclass.

upcasting - taking an instance of a class and casting it to its 
superclass. This will *always* work. Every class you create in D can be 
cast to Object, since all classes implicitly derive from Object.



More information about the Digitalmars-d-learn mailing list