user1423893
user1423893

Reputation: 796

Only allowing specific object types to be passed into a method based on a derived class type

I have a base class which has a method call AddFruit that takes a class of Fruit type and processes it in a general way.

    public abstract class Foo
    {
        protected List<ProcessedFruit> processedFruit = new List<ProcessedFruit>();

        public void AddFruit(Fruit o)       
        {
            // Process fruit

            processedFruit.Add(o);
        }

        public void Update()
        {
            // Do base class specific stuff here
            OnUpdate();
        }

        protected abstract void OnUpdate();
    }

    public class AppleBar : Foo
    {
        public AppleBar()
            :base(){}

        protected override void OnUpdate() { }
    }

    public class BananaBar : Foo
    {
        public BananaBar()
            :base(){}

        protected override void OnUpdate() { }
    }

Any class which derives from Foo is updated in a non general way and will use the list of ProcessedFruit in a different manner.

Fruit can be added and processed any time after the Bar class has been instantiated.

    public abstract class Fruit
    {

    }

    public class Banana : Fruit
    {

    }

    public class Apple : Fruit
    {

    }

I'm wondering, is it possible to only allow a particular type of Fruit class to be added based on the derived Bar class type?

For example:

I understand that I could override the AddFruit method but I would like the processing to remain in the base class and would like to avoid calling base.AddFruit in the overridden methods associated with the BananaBar and AppleBar derived classes.

I also wish to avoid checking the type of Fruit using GetType().

Ideally I would like something as follows:

var o = new AppleBar()

// This has to be an Apple and intellisense can recognise this 
o.AddFruit(...);          

Is this possible?

Edit:

I am having problems with the following using generics:

 List<Foo<Fruit>> commands = new List<Foo<Fruit>>(10);

 commands.Add(new AppleBar());    // Can't be added
 commands.Add(new BananaBar());   // Can't be added

Upvotes: 2

Views: 150

Answers (1)

Ben Aaronson
Ben Aaronson

Reputation: 6975

The easiest way to do this is with a generic type parameter on the base class, which then gets filled in with a specific type by the inheriting class:

public abstract class Foo<T> where T : Fruit
{
    protected List<ProcessedFruit> processedFruit = new List<ProcessedFruit>();

    public void AddFruit(T o)       
    {
        // Process fruit

        processedFruit.Add(o);
    }

    public void Update()
    {
        // Do base class specific stuff here
        OnUpdate();
    }

    protected abstract void OnUpdate();
}

public class AppleBar : Foo<Apple>
{
    //...
}

Update

See this answer for an explanation of why you can't add an AppleBar to a List<Foo<Fruit>>

Upvotes: 6

Related Questions