views:

294

answers:

6

I'm not sure it's really a "polymorphism" question but anyway... So I have an abstract class and 2 other classes that inherit from it.

Some code from the base class have a variable that would be different between classes that extends the base class.

What's the best way to do that? Override a "get" method? Change the architecture a little to call a function from the base classe to the extended class that would pass the value...

Here's an example (it won't compile, just a little example on how I did it) :

public abstract class BaseAbstract class {

  ... some code ....

  // Here "listName" would change depending on the extending class
  protected List<Items> getAllItems(String listName) {

    Web.getList(listName);

    ... some code ...

  }

  protected abstract List<Items> getAllItems();

}

public class NewClass : BaseAbstract {
 protected override void getAllItems() {
    return getAllItems("ListNameOfNewClass");
 }
}

That's how I did it, but it doesn't feel really clear and easy to maintain IMO.

Any idea or comment welcome!

A: 

not sure it's the right answer, but you could have a base class protected variable that you set in the inherited classes during initialization?

eg:

class test
{
    protected string listName;

    protected void getAllItems() 
    {
        return getAllItems(listName);
    }
}

class test2 : test
{
    public test2()
    {
        base.listName = "MyUniqueList";
    }
}
Sk93
problem with this is that is doesn't force the child to set the listName. If you didn't write the original base class, how would you know to set it?
ctacke
protected abstract property with a get; defined. It would force the developer to implement it
Sekhat
+7  A: 

I'd probably opt for something like this:

public abstract class Base
{
    protected abstract string ListName { get; }
    public List<Item> GetItems()
    {
        return Web.GetList(ListName);
    }
}

public class Child : Base
{
    protected override string ListName
    {
        get { return "MyListName"; }
    }
}
ctacke
I think it's the best way because it's easier to maintain and simple. As stated, it's not the best way to do it if that's that only thing you need to "specialize", but in my case I think it's perfect. Thank you!
+2  A: 

I would probably go for the following approach:

public abstract class Base
{
    protected List<Items> getAllItems(String listName) 
    {
        // Implementation
    }

    public abstract List<Items> Items
    {
        get;
    }
}

public class NewClass : Base
{
    public override List<Items> Items
    {
        get
        {
            return base.getAllItems("ListNameOfNewClass");
        }
    }
}

This keeps the internal protected functionality (getAllItems) separate from the publicly exposed method / property, and also means that its still available to any classes which inherit from NewClass.

I've changed your interface and exposed it as a property purely out of pig-headedness! And party just in case you didnt know it could be done...

Kragen
I agree that I'd use a Property myself. The issue I have with this implementation, however, is that it's confusing to a developer coming along later in the project. They have to know that their Items property needs to call back up to the base, and that's not at all obvious.
ctacke
As long as the role of the base class is well defined and documented i don't think it would cause massive issues, but having had a chance to look over the other answers I'd probably go for composition for this reason.
Kragen
A: 

I think it would make more sense implementing a third component:

    public abstract class BaseClass {

        protected abstract IList<Item> getAllItems();
    }

    public class SubClass : BaseClass 
    {
        IItemsProvider itemsProvider;

        protected override IList<Item> getAllItems() 
        {
            return itemsProvider.getAllItems("filter");
        }
    }

    public interface IItemsProvider
    {
        IList<Item> getAllItems(string name);
    }
bruno conde
I don't know if I'm right but I find this solution a little bit too complicated, no?
+4  A: 

Prefer Composition Over Inheritance.

public class Base {
  private ItemListGetter itemListGetter; // assignment/initialization is up to you

  private List<Items> getAllItems() {  // this can now be inlined
    return itemListGetter.getList();
  }

}

If this is the only dimension of variation between your subclasses, there's no longer a need for inheritance here; just establish the right ItemListGetter as needed.

Carl Manaster
I'll keep that in mind! Thanks for your input! :)
A: 

If you really want to do the inheritance, then I'd opt for ctacke's solution.

Generally however your problem doesn't seem to be solved with inheritance. Inheritance should just be used to provide specialized behavior. In your case however it seems more to be a configuration issue. Meaning you should provide a property (i.e. the list-name) which you configure from outside, without any need for subclassing.

Juri
Well I have specialized methods too, just not in my example.