C#Abstract类有另一个抽象类对象

时间:2015-12-17 21:56:49

标签: c# oop inheritance abstract

我有几个类代表一些测量数据,首先是<div class="wrapper"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> <div>10</div> <div>11</div> <div>12</div> <div>13</div> <div>14</div> <div>15</div> <div>16</div> <div>17</div> <div>18</div> <div>19</div> <div>20</div> <div>21</div> <div>22</div> <div>23</div> <div>24</div> <div>25</div> <div>26</div> <div>27</div> <div>28</div> <div>29</div> <div>30</div> <div>31</div> </div>抽象类,派生ICutRoundCut,如下所示:

SquareCut

当然它包含一些实现,但对于这个问题并不重要。 public abstract class ICut { } public class RoundCut : ICut { DoSomeWithRoundCut(){} } public class SquareCut : ICut { DoSomeWithSquareCut(){} } 是抽象类而不是接口,因为它本身就有一些实现。

然后,这里是代表ICut数据集的类,同样是基础抽象ICut和派生IRollRoundRoll

SquareRoll

现在,我当然无法通过以下方式直接联系public abstract class IRoll { // list of measured cuts public List<ICut> cuts; // Create new cut public abstract ICut CreateCut(); } public class RoundRoll : IRoll { public RoundRoll () { cuts = new List<RoundCut>(); } public override ICut CreateCut() { RoundCut cut = new RoundCut(); cuts.Add(cut); return cut; } } public class SquareRoll : IRoll { public SquareRoll() { cuts = new List<SquareCut>(); } public override ICut CreateCut() { SquareCut cut = new SquareCut(); cuts.Add(cut); return cut; } } RoundCut额外实施:

SquareCut

我不能同时使用:

IRoll roll = new RoundRoll();
roll.CreateCut();
roll.cuts[0].DoSomeWithRoundRoll();

因为我通常不知道(roll.cuts[0] as RoundCut).DoSomeWithRoundRoll(); 派生IRoll是哪个。

我正在重构一个庞大的项目,其中所有roll个对象都是roll类型,现在必须添加另一个。

也许我错过了某种合适的设计模式,我在高级OOP模式学习曲线的开头,我一直在考虑解决这个问题。< / p>

更新 经过多次实验,我意识到,与我的主要观点相反,我最终得到了@ The-First-Tiger的解决方案,并进行了一些改进。我创建了简单的工厂:

RoundRoll

所以我可以创建像:

// Cut factory
public static class CutFactory
{
    // Get new cut by given shape type
    public static ICut GetCut(RollShape shape)
    {
        switch (shape)
        {
            case RollShape.Round:
                return new RoundCut();
            case RollShape.Square:
                return new SquareCut();
            default:
                throw new ArgumentException();
        }
    }
}

如果需要有不同的行为:

ICut cut = CutFactory.GetCut(roll.GetShape());

1 个答案:

答案 0 :(得分:4)

解决此问题的一种方法是对IRoll的类型ICut进行通用:

public abstract class AbstractRoll<T> where T : ICut, new {
    // list of measured cuts
    public List<T> cuts = new List<T>();
    // Create new cut
    public T CreateCut() {
       var res = new T();
       curs.Add(res);
       return res;
    }
}

现在你可以这样做:

public class RoundRoll : AbstractRoll<RoundCut> {
    ...
}

public class SquareRoll : AbstractRoll<SquareCut> {
    ...
}

请注意,C#允许您通过将约束应用于泛型类型来将样板代码移动到基类。

现在唯一剩下的问题是AbstractRoll不再是RoundRollSquareRoll的通用界面,因此您无法创建广告系列。

这个问题可以通过在IRoll类之上添加一个非通用接口AbstractRoll来解决,该接口具有所有卷的通用操作,并且也与卷的类型无关。 ICut

public interface IRoll {
    IEnumerable<ICut> Cuts { get; }
    ... // add other useful methods here
}
public abstract class AbstractRoll<T> : IRoll where T : ICut, new {
    ...
    public IEnumerable<ICut> Cuts {
        get {
            return curs.Cast<ICut>();
        }
    }
    ... // implement other useful methods here
}