简体   繁体   English

具有通用子类型的抽象类

[英]Abstract Class with Generic Subtype

I implemented an abstract class like the following: 我实现了如下的抽象类:

public abstract class Pack
{
    protected List<PackEntry> m_Entries;

    public Int32 EntriesCount
    {
        get { return m_Entries.Count; }
    }

    public Pack()
    {
        m_Entries = new List<PackEntry>();
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackTypeA : Pack { ... }
public sealed class PackTypeB : Pack { ... }

And a PackEntry subclass also: PackEntry子类还可以:

public abstract class PackEntry
{
    protected Byte[] m_Data;

    protected PackEntry() { }

    public Byte[] GetData()
    {
        return m_Data;
    }

    public void SetData(Byte[] data)
    {
        m_Data = data;
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackEntryTypeA : PackEntry { ... }
public sealed class PackEntryTypeB : PackEntry { ... }

This means that the derived class PackTypeA will use PackEntryTypeA entries and PackTypeB will use PackEntryTypeB and so on. 这意味着派生类PackTypeA将使用PackEntryTypeA条目,而PackTypeB将使用PackEntryTypeB ,依此类推。 Now... I'm using my Pack abstract class as in the following code snippet: 现在...我正在使用我的Pack抽象类,如以下代码片段所示:

Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();
pack.AbstractMethod1();

if (condition)
    pack.AbstractMethod2();

...

Everything works like a charm but inside AbstractMethod1() ... AbstractMethodN() overrides I'm working a lot with the entries list. 一切都像一个魅力,但在AbstractMethod1()内部... AbstractMethodN()覆盖了我正在处理的条目列表。 Which needs a lot of casting like: 需要大量的转换,例如:

for (Int32 i = 0; i < m_Entries.Count; ++i)
{
    PackEntryTypeA entry = (PackEntryTypeA)m_Entries[i];
    ...

It's getting tedious. 它变得乏味。 So I tried the following approach implementing a generic type to my Pack class: 因此,我尝试了以下方法来对我的Pack类实现通用类型:

public abstract class Pack<T> where T : PackEntry
{
    protected List<T> m_Entries;

    public Int32 EntriesCount
    {
        get { return m_Entries.Count; }
    }

    public Pack()
    {
        m_Entries = new List<T>();
    }

    #region Methods: Abstract
    ...
    #endregion
}

public sealed class PackTypeA : Pack<PackEntryTypeA> { ... }
public sealed class PackTypeB : Pack<PackEntryTypeB> { ... }

Which is much, much, much better! 哪个好很多! But the problem is that I can't use the following code snippet anymore: 但是问题是我不能再使用以下代码片段:

Pack pack = useTypeA ? new PackTypeA() : new PackTypeB();

Because it requires the generic type to be specified (which I really can't): 因为它需要指定泛型(我真的不能):

Pack<PackTypeN>

The last solution I figured out is to move the list to the derived classes but it's not very elegant. 我想出的最后一个解决方案是将列表移到派生类,但这不是很优雅。 Can someone kindly point me to a solution please? 有人可以请我指出解决方案吗?

Pack<PackEntryTypeA> and Pack<PackEntryTypeB> are different types, so, to be able to store them in a same variable they have to have same base class or interface. Pack<PackEntryTypeA>Pack<PackEntryTypeB>是不同的类型,因此,要能够将它们存储在相同的变量中,它们必须具有相同的基类或接口。

public static void Main()
{
    var pack = 1 == 1 ? (IPack)new PackTypeA() : (IPack)new PackTypeB();
    pack.AbstractMethod1();
    pack = 1 == 2 ? (IPack)new PackTypeA() : (IPack)new PackTypeB();
    pack.AbstractMethod1();
}

public interface IPack { void AbstractMethod1(); }

public abstract class PackEntry { }

public sealed class PackEntryTypeA : PackEntry {}
public sealed class PackEntryTypeB : PackEntry {}

public abstract class Pack<T> : IPack where T : PackEntry
{
    protected List<T> m_Entries = new List<T>();
    public abstract void AbstractMethod1();
}

public sealed class PackTypeA : Pack<PackEntryTypeA> 
{
    public override void AbstractMethod1() 
    { 
        Console.WriteLine(m_Entries.GetType().ToString());
    }
}

public sealed class PackTypeB : Pack<PackEntryTypeB> 
{
    public override void AbstractMethod1() 
    { 
        Console.WriteLine(m_Entries.GetType().ToString());
    }
}

Output: 输出:

System.Collections.Generic.List`1[PackEntryTypeA]
System.Collections.Generic.List`1[PackEntryTypeB]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM