Question

I have the following scenario and I'm trying to figure out what design pattern to place in the for loop.

The query will only ever return Bananas or Apples. Never a mix of bananas and apples. I know ahead of time when calling DoStuff, whether Bananas or Apples will be returned because I can control the query.

I've been trying an approach of passing through an interface as a second parameter to DoStuff that would either set the length of banana or diameter of apple.

Any suggestions as how I could achieve this? I need DoStuff to be re-usable.

    public class BaseClass
    {

    }

    public class Apple : BaseClass
    {
        public int Diameter { get; set; }
    }

    public class Banana : BaseClass
    {
        public int Length { get; set; }
    }

    public void DoStuff(Query query)
    {
        // The query only ever returns bananas OR Apples. Never both.
        var items = repository.GetItems<BaseClass>(query);

        foreach (var item in items)
        {
            // Code to run some arbitrary calculation then set Length if Banana
            // Code to run some arbitrary calculation then set Diameter if Apple
        }
    }
Was it helpful?

Solution

Why have a base class if no derived class shares any behaviour or data? You should look into Liskov Substitution principle (LSP). LSP basically says that correct systems adhere to strong behavioural subtyping and that in a polymorphic scenario when one type is substituted for another it will not violate correctness, etc.

You're clearly violating this principle by having two subclasses with nothing real in common. I would suggest you look at a different way of approaching this and provide more detail on what you want to accomplish so someone might be able to help you accomplish what you need.

Without knowing more about what you're trying to do, here's something I would suggest:

public abstract class BaseClass
{
    public abstract void DoSomething();
}

public class Apple : BaseClass
{
    public int Diameter { get; set; }
    public override void DoSomething()
    {
        // Do something specific for Apple
    }
}
//...
public void DoStuff(Query query)
{
    // The query only ever returns bananas OR Apples. Never both.
    var items = repository.GetItems<BaseClass>(query);

    foreach (var item in items)
    {
        item.DoSomething();
    }
}

OTHER TIPS

You can write your DoStuff method like this

public void DoStuff(Query query)
{
    // The query only ever returns bananas OR Apples. Never both.
    var items = repository.GetItems<BaseClass>(query);

    foreach (var item in items.OfType<Banana>())
    {
        // Code to set Length if Banana
    }
}

but I do prefer the Liskov Substitution principle...

I'd make DoStuff an abstract method in BaseClass and override it in Apple & Banana:

public class BaseClass
{
    // Stuff common to Apples & Bananas here

    public abstract void DoStuff(Query query);

}

public class Apple : BaseClass
{
    public int Diameter { get; set; }

    public override DoStuff(Query query)
    {
        // Implementation for Apples
    }
}

public class Bananas : BaseClass
{
    public int length { get; set; }

    public override DoStuff(Query query)
    {
        // Implementation for Bananas
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top