派生类设计问题(多态)

发布于 2024-12-02 02:57:33 字数 1800 浏览 0 评论 0原文

设计问题如下,实际问题由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 中处理(a/c 参考丢失)。

这是将模块 2 的派生类对象转换为模块 1 类对象的唯一方法,

我希望我已经清楚地解释了这个问题,如果没有,我深表歉意,非常感谢解决这个问题。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最冷一天 2024-12-09 02:57:33

如果我正确理解您的问题,您想要的是将 IList 视为 IList。这在 C# 中是不可能的,并且有很好的理由:IList 说可以做的事情之一是“尝试将任何 LetterA 添加到它。这对于 IList 是不可能的,因此没有内置的方法可以完成您想要的操作。

您可以做的是创建您自己的 IList 实现,它包装派生类型的另一个 IList:(

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 的 setter 可能如下所示:

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

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> that wraps another 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
}

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

Your setter for ALetters could then look like this:

_aLetters = value;
if(_aLetters == null)
    base.ALetters = null;
else
    base.ALetters = new BaseTypeList<LetterA, LetterSmallA>(value);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文