Problema de diseño de clases derivadas (polimorfismo)

The design problem is as follows, actual problem consists of 2 modules.

Module 1 classes (External Assembly)

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

Module 2 classes

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 
    }
}

Essentially derived classes are generated in the module 2 and processed in the external assembly module 1, on a/c reference loss.

Is the only way to translate the derived class objects of the module 2 to module 1 class objects

I hope i have been explain clearly the issue, if not i do apologise, would really appreciate solutions to this.

preguntado el 27 de agosto de 11 a las 15:08

what do you mean by saying "on a/c reference loss" ? -

the .ToList() returns a copy rather than returning a casted reference, -

essentially what i would like achieve is static type constraint, also by not using additional property -

thank you for the link ckoenig -

1 Respuestas

If I understand your question correctly, what you want is to treat IList<LetterSmallA> as IList<LetterA>. This is not possible in C# and for very good reasons: one of the things IList<LetterA> says is possible to do with is is to “try to add any LetterA to it. This is not possible with IList<LetterSmallA> and so there is no built-in way to do what you want.

What you can do is to create your own implementation of IList<T> que envuelve a otro IList<T> of derived type:

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
}

(La class constraints are not necessary, but make some code simpler.)

Tu setter para ALetters could then look like this:

_aLetters = value;
if(_aLetters == null)
    base.ALetters = null;
else
    base.ALetters = new BaseTypeList<LetterA, LetterSmallA>(value);

Respondido 27 ago 11, 19:08

but then how would that solve the problem ? as i can not modify the external assembly, might as well just translate the module 2 class object into module 1 class object. - kalki

If you think my answer actually answered your question, you should aceptarlo. - svick

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.