Exitos
Exitos

Reputation: 29720

How to infer a type in a base class dependant on the inheriting class at runtime without if statements?

I have this little OO problem..

abstract class MyAbstractBaseClass
{    
   MyHelperClassBase myHelperBaseClass;

   protected method foo()
   {
       //QUESTION....... :  when I am here I want to do this...

       myHelperBaseClass = new MyHelperSubClass(); 

       //OR...

       myHelperBaseClass = new MyOtherHelperSubClass();

       //HOWEVER ITS COMPLETELY CONDITIONAL ON THE BASE CLASS
       //HOW DO I MAKE SURE THE CORRECT TYPE IS INSTANTIATED DEPENDANT ON
       //THE BASE CLASS WITHOUT USING AN 'if' STATEMENT?
   }    
}

class MySubClass : MyAbstractClass {}    
class MyOtherSubClass : MyAbstractClass {}    
/////////////

abstract class MyHelperClassBase {}    

class MyHelperSubClass : MyHelperClassBase, IMyHelper {}    
class MyOtherHelperSubClass : MyHelperClassBase, IMyHelper {}

I want to be able to have a the type basically passed up but cant think of a slick way to do this. Should I just stuck an abstract property on the base class?

Upvotes: 1

Views: 81

Answers (2)

Joel B Fant
Joel B Fant

Reputation: 24756

The older OO way of solving this (without generics) involves a virtual or abstract method on the base that the derived classes must implement. This is pretty common in parallel hierarchies like your example:

abstract class MyAbstractClass{

    MyHelperClassBase myHelper;

    protected void foo() {
        myHelper = createHelper();
    }

    protected abstract MyHelperClassBase createHelper();
}

class MySubClass : MyAbstractClass{
    protected override MyHelperClassBase createHelper(){
        return new MyHelperSubClass();
    }
}

class MyOtherSubClass : MyAbstractClass{
    protected override MyHelperClassBase createHelper(){
        return new MyOtherHelperSubClass();
    }
}

Generics come in very handy, but sometimes it's good to know this way, too.

Upvotes: 0

Reed Copsey
Reed Copsey

Reputation: 564403

Your goals are somewhat unclear. If the goal is to associate a helper class with a specific implementation of the class, there are a couple of options.

You can use generics:

abstract class MyAbstractBaseClass<T> where T : MyHelperClassBase, new()
{
     T myHelper;

     protected void Foo()
     {
         myHelper = new T(); // This will be the appropriate subclass
     }
}

// Derived classes become ...
class MySubClass : MyAbstractClass<MyHelperSubClass>
{
}

// Derived classes become ...
class MyOtherSubClass : MyAbstractClass<MyOtherHelperSubClass>
{
}

Alternatively, you could have an abstract property in the base class, and the subclasses could implement it:

abstract class MyAbstractBaseClass<T> where T : MyHelperClassBase, new()
{
     MyHelperClassBase myHelper;

     abstract protected Func<MyHelperClassBase> MyHelperClassBaseFactory { get; }

     protected void Foo()
     {
         // Construct as needed...
         myHelper = MyHelperClassBaseFactory();
     }

}

// Derived classes implement...
class MySubClass : MyAbstractClass
{
     protected override Func<MyHelperClassBase> MyHelperClassBaseFactory 
     { 
         get { return () => new MyHelperSubClass(); }
     }
}

Upvotes: 3

Related Questions