Производная задача проектирования класса (Полиморфизм) - PullRequest
1 голос
/ 27 августа 2011

Проблема проектирования заключается в следующем, актуальная проблема состоит из 2 модулей.

Классы модуля 1 (внешняя сборка)

abstract class Letter
{
    private int _id;
    protected Letter(int id) { _id = id; }

    public abstract string Val { get; }
}

class LetterA : Letter
{
    public LetterA(int id) : base(id) {}

    public override string Val
    {
        get { return "A"; }
    }
}

class WordWithALettersOnly
{
    public IList<LetterA> ALetters { get; set; }
}

Классы модуля 2

class LetterSmallA : LetterA 
{
    public LetterSmallA(int id) : base(id) {}
    public override string Val
    {
        get { return "a"; }
    }
}

class WordWithSmallALettersOnly : WordWithALettersOnly
{
    private IList<LetterSmallA> _aLetters;
    public new IList<LetterSmallA> ALetters
    {
        get { return _aLetters; }
        set
        {
            _aLetters = value;
            if(_aLetters != null)
                base.ALetters = value.Cast<LetterA>().ToList(); // <-- reference lost
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var smallAWordOnly = new WordwithSmallALettersOnly();
        smallAWordOnly.ALetters = new List<LetterSmallA>(){new LetterSmallA(1)};
        Console.WriteLine("d : " + smallAWordOnly.ALetters.Count); // --> 1
        Console.WriteLine("b : " + ((WordwithALettersOnly)smallAWordOnly).ALetters.Count); // --> 1
        smallAWordOnly.ALetters.Add(new LetterSmallA(2)); --> 2
        Console.WriteLine("d : " + smallAWordOnly.ALetters.Count);
        Console.WriteLine("b : " + ((WordwithALettersOnly)smallAWordOnly).ALetters.Count); // -> 1 
    }
}

По существу производные классы генерируются в модуле 2 и обрабатываются во внешнем модуле сборки 1 при потере ссылки на кондиционер.

Это единственный способ преобразовать объекты производного класса модуля 2 в класс модуля 1.объекты

Надеюсь, я четко объяснил проблему, если не извинюсь, то был бы очень признателен за решение этой проблемы.

1 Ответ

0 голосов
/ 27 августа 2011

Если я правильно понимаю ваш вопрос, вам нужно трактовать IList<LetterSmallA> как IList<LetterA>.Это невозможно в C # и по очень веским причинам: одна из вещей, с которыми IList<LetterA> говорит, что это можно сделать, это «попытаться добавить к ней LetterA.Это невозможно с IList<LetterSmallA>, и поэтому нет встроенного способа сделать то, что вы хотите.

Что вы можете сделать, это создать собственную реализацию IList<T>, которая обернет другую IList<T>производный тип:

class BaseTypeList<TBase, TDerived> : IList<TBase>
    where TBase : class
    where TDerived : class, TBase 
{
    private readonly IList<TDerived> m_derivedList;

    public BaseTypeList(IList<TDerived> derivedList)
    {
        m_derivedList = derivedList;
    }

    public IEnumerator<TBase> GetEnumerator()
    {
        return m_derivedList.Cast<TBase>().GetEnumerator();
    }

    public void Add(TBase item)
    {
        var derivedItem = item as TDerived;
        if (derivedItem == null)
            throw new ArgumentException();
        m_derivedList.Add(derivedItem);
    }

    public void Clear()
    {
        m_derivedList.Clear();
    }

    // other members implemented in a similar fashion
}

(ограничения class необязательны, но упрощают код.)

Ваш установщик для ALetters может выглядеть следующим образом:

_aLetters = value;
if(_aLetters == null)
    base.ALetters = null;
else
    base.ALetters = new BaseTypeList<LetterA, LetterSmallA>(value);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...