通用型工厂

时间:2015-11-05 23:06:14

标签: c# generics factory

假设我有一个Fruit Tree的通用类,以及一些指定的树:

    abstract class FruitTree
    {
        public abstract String getFruitName();
    }

    class AppleTree : FruitTree
    {
        public override String getFruitName()
        {
            return "Apple";
        }
    }

    class OrangeTree : FruitTree
    {
        public override String getFruitName()
        {
            return "Orange";
        }
    }

我想做的是创建一个果树工厂:

    public static int APPLE = 0;
    public static int ORANGE = 1;

    public class FruitFactory
    {
        public List<FruitTree> getYummyFruitTrees(int type)
        {
            switch (type)
            {
                case 0:
                    return new List<AppleTree>();
                case 1:
                    return new List<OrangeTree>();
                default:
                    return null;
            }
        }
    }

但是C#不允许这样做。怎么能这样呢?我不在乎是否有AppleTrees of OrangeTrees,我只想获得FruitTrees列表。

编辑: 我必须编辑我的问题,因为这个例子太简单了:

这个例子是为了简单而给出的,但它给出了问题的本质 - 我的问题是我有一个处理算法类,它使用较小的类作为处理元素。例如,Matrix,它使用特定类型的单元格(BaseCell)。

    public class Matrix<T> where T : BaseCell
    {
        (...)
    }

我必须开发这种算法的一种分支,它使用大部分基本代码,但也使用扩展单元格,例如:

    public class ExtendedCell : BaseCell
    {
        (...)
    }

    public class SuperMatrix : Matrix<ExtendedCell>
    {   
        (...)
    }

而且,最后,我有一个这个算法的跑步者,它管理在theads等上运行它。

    public class AlgRunner 
    {
        Matrix<BaseCell> algToRun;

        public AlgRunner(Matrix<BaseCell> alg)
        {
            algToRun = alg;
        }
    }

我只是想使用它的一些基类字段/方法,我不需要知道它是哪个算法分支,所以我必须使用继承而不是实现interfece。在Java中,我有更多的经验,这不是问题,但我不知道如何在这里实现它。

2 个答案:

答案 0 :(得分:2)

从您添加的附加信息中可以看出,您无法使用具体类完成您正在寻找的内容。但是,您可以使用接口来执行此操作,前提是您不需要同时对输出和输入类型(即协方差和逆变)进行差异。

你可以构建:

public class IMatrix<out T> where T : BaseCell
{
    T Cell { get; }

    ....
}

这里可以有类型为T的输出参数,但没有类型为T的输入参数。

public class IMatrix<in T> where T : BaseCell
{
    void FunctionOnCell(T cell);

    ....
}

这里你可以有类型为T的输入参数,但没有类型为T的输出参数。

我认为,对于您的用例,协变(out)示例是您正在寻找的示例。

假设您使用了协变接口,那么即使实际的具体类是IMatrix<BaseCell>,您的算法运行器也可以接受Matrix<ExtendedCell>类型的参数。

public class AlgRunner 
{
    IMatrix<BaseCell> algToRun;

    public AlgRunner(IMatrix<BaseCell> alg)
    {
        algToRun = alg;
    }
}

有关创建协变和逆变接口的更多详细信息,请参阅https://msdn.microsoft.com/en-us/library/dd997386.aspx

答案 1 :(得分:-3)

这个应该有帮助

 public IEnumerable<FruitTree> getYummyFruitTrees(int type)
            {
                switch (type)
                {
                    case 0:
                        return new List<AppleTree>();
                    case 1:
                        return new List<OrangeTree>();
                    default:
                        return null;
                }
            }