C # основной вопрос полиморфизма - PullRequest
1 голос
/ 31 июля 2009

Я не уверен, что это действительно вопрос "полиморфизма", но в любом случае ... Итак, у меня есть абстрактный класс и 2 других класса, которые наследуют его.

У некоторого кода из базового класса есть переменная, которая будет отличаться между классами, расширяющими базовый класс.

Какой лучший способ сделать это? Переопределить метод get? Немного измените архитектуру, чтобы вызвать функцию из базового класса в расширенный класс, который будет передавать значение ...

Вот пример (он не скомпилируется, просто небольшой пример того, как я это сделал):

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");
 }
}

Вот как я это сделал, но это не очень понятно и легко поддерживать IMO.

Любая идея или комментарий приветствуются!

Ответы [ 6 ]

7 голосов
/ 31 июля 2009

Я бы, наверное, выбрал что-то вроде этого:

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"; }
    }
}
4 голосов
/ 31 июля 2009

Предпочитают состав перед наследованием.

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

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

}

Если это единственное измерение различий между вашими подклассами, здесь больше нет необходимости наследования; просто установите нужный ItemListGetter по мере необходимости.

2 голосов
/ 31 июля 2009

Я бы, вероятно, выбрал следующий подход:

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");
        }
    }
}

Это позволяет отделить внутреннюю защищенную функциональность (getAllItems) от открытого метода / свойства, а также означает, что она по-прежнему доступна для любых классов, наследуемых от NewClass.

Я изменил ваш интерфейс и выставил его как свойство исключительно из-за безумия! И вечеринка на тот случай, если ты не знал, что это можно сделать ...

0 голосов
/ 31 июля 2009

Если вы действительно хотите наследовать, я бы выбрал решение ctacke .

Однако, как правило, ваша проблема не решается с помощью наследования. Наследование должно использоваться только для обеспечения специализированного поведения. В вашем случае, однако, кажется, что это больше проблема конфигурации. Это означает, что вы должны предоставить свойство (то есть имя списка), которое вы конфигурируете извне, без необходимости в подклассах.

0 голосов
/ 31 июля 2009

Я думаю, что было бы более разумно реализовать третий компонент:

    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);
    }
0 голосов
/ 31 июля 2009

не уверен, что это правильный ответ, но вы могли бы иметь защищенную переменную базового класса, которую вы установили в унаследованных классах во время инициализации?

например:

class test
{
    protected string listName;

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

class test2 : test
{
    public test2()
    {
        base.listName = "MyUniqueList";
    }
}
...