locked
Deriving from a hierarchy of abstract classes RRS feed

  • Question

  • Hi there,

    I'm designing a system in which I have an abstract class that hosts properties that point to instances of abstract classes as well, so I have a hierarchy of abstract classes.

    Let's say I have a base class Vehicle, with a property named Properties of the abstract type VehicleProperties. Now, I have a Car class that derives from Vehicle. I derive CarProperties from VehicleProperties... Ok, fine, but now when I program against the deriven Car class, I would like to see Car.Properties as CarProperties, not as VehicleProperties.

    Of course I can do that by hiding:

    public new VehicleProperties Properties{
       get { return (VehicleProperties)this._properties; }
    }

    But is this the preferred way?

    Anyone?

    Marc

    Monday, January 29, 2007 4:59 PM

Answers

  • Each level in your hierarchy must rely on only the information available to it at that level.  Therefore while in the Vehicle abstract class you can only rely on the VehicleProperties class for the properties.  To do otherwise would violate the entire purpose of abstraction.  However you can define new members in derived classes that expose the more specific information.  For example given this layout:

    public class Vehicle
    {
       private VehicleProperties m_Props;
       public virtual VehicleProperties Properties
       {
          get { return m_Props; }
          set { m_Props = value; }
       }
    }

    You can do this in a derived class.

    public class Car : Vehicle
    {
       public override VehicleProperties Properties
       {
          get { return base.Properties; }
          set
          {
             if (!(value is CarProperties))
                throw New ArgumentException(...);

             base.Properies = value;
          }
       }

       protected CarProperties CarProperties
       {
          get { return m_Props as CarProperties; }
          set { m_Props = value; }
       }
    }

    In this case you can internally use the type-safe CarProperties to do your work while the interface remains the same.  Of course you could also make it public but I shy away from that design because you are now exposing the same field in different manners which can be confusing.  Also note that you could use generics to remove the need for this typecasting all together:

    public class Vehicle<PROPERTYTYPE>
    {
        private PROPERTYTYPE m_Props;

        public virtual PROPERTYTYPE Properties
        {
           get { return m_Props; }
           set  { m_Props = value; }
        }
    }

    This works well for narrow hierarchies but less so for deep hierarchies.

    Michael Taylor - 1/29/07
    http://p3net.mvps.org

     

    Monday, January 29, 2007 6:29 PM
    Moderator

All replies

  • Each level in your hierarchy must rely on only the information available to it at that level.  Therefore while in the Vehicle abstract class you can only rely on the VehicleProperties class for the properties.  To do otherwise would violate the entire purpose of abstraction.  However you can define new members in derived classes that expose the more specific information.  For example given this layout:

    public class Vehicle
    {
       private VehicleProperties m_Props;
       public virtual VehicleProperties Properties
       {
          get { return m_Props; }
          set { m_Props = value; }
       }
    }

    You can do this in a derived class.

    public class Car : Vehicle
    {
       public override VehicleProperties Properties
       {
          get { return base.Properties; }
          set
          {
             if (!(value is CarProperties))
                throw New ArgumentException(...);

             base.Properies = value;
          }
       }

       protected CarProperties CarProperties
       {
          get { return m_Props as CarProperties; }
          set { m_Props = value; }
       }
    }

    In this case you can internally use the type-safe CarProperties to do your work while the interface remains the same.  Of course you could also make it public but I shy away from that design because you are now exposing the same field in different manners which can be confusing.  Also note that you could use generics to remove the need for this typecasting all together:

    public class Vehicle<PROPERTYTYPE>
    {
        private PROPERTYTYPE m_Props;

        public virtual PROPERTYTYPE Properties
        {
           get { return m_Props; }
           set  { m_Props = value; }
        }
    }

    This works well for narrow hierarchies but less so for deep hierarchies.

    Michael Taylor - 1/29/07
    http://p3net.mvps.org

     

    Monday, January 29, 2007 6:29 PM
    Moderator
  • Thanks Michael, this has been helpful.

    Tuesday, January 30, 2007 7:38 AM