簡體   English   中英

C#抽象類具有另一個抽象類對象

[英]C# Abstract class has another abstract class object

我很少代表一些測量數據的類,起初, ICut抽象類具有派生的RoundCutSquareCut如下所示:

public abstract class ICut
{
}

public class RoundCut : ICut
{
    DoSomeWithRoundCut(){}
}

public class SquareCut : ICut
{
    DoSomeWithSquareCut(){}
}

當然,它包含一些實現,但是對於這個問題並不重要。 ICut是抽象類而不是接口,因為它本身具有一些實現。

然后,這是代表ICut數據集的類,再次基於抽象IRoll以及派生的RoundRollSquareRoll

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

而現在,我當然無法通過調用例如以下SquareCut直接達到RoundCutSquareCut額外實現:

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

而且我不能使用:

(roll.cuts[0] as RoundCut).DoSomeWithRoundRoll();

因為我通常不知道哪個IRoll派生roll是。

我正在重構一個大型項目,其中所有roll對象均為RoundRoll類型,現在必須添加其他對象。

也許我缺少某種合適的設計模式,正處於高級OOP模式學習曲線的開始,並且我一直在全天候在考慮解決此問題的方法。

更新經過多次實驗,我意識到與我的主要觀點相反,我最終對@ The-First-Tiger的解決方案進行了一些改進。 我創建了簡單的工廠:

// 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();
        }
    }
}

所以我可以像這樣創建Cut:

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

並且如果需要具有不同的行為:

if (cut is RoundCut) 
    (cut as RoundCut).RoundCutSpecificMethod();
else if (cut is SquareCut) 
    (cut as SquareCut).SquareCutSpecificMethod();

解決該問題的一種方法是使IRoll在其ICut類型上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的通用接口,因此您無法創建紙卷集合。

可以通過在AbstractRoll類的頂部添加非通用接口IRoll來解決此問題,該接口具有所有卷所共有的操作,並且也與卷的ICut類型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
}

您可以使用以下接口重寫代碼:

public interface ICut
{
   DoSomething();
}

public class RoundCut : ICut
{
    DoSomething(){}
}

public class SquareCut : ICut
{
    DoSomething(){}
}

public interface IRoll
{
    IEnumerable<ICut> Cuts { get; };      

    ICut CreateCut();
}

public class RoundRoll : IRoll
{        
    public IEnumerable<ICut> Cuts { get; private set; }

    public RoundRoll ()
    {
        this.Cuts = new List<ICut>();
    }

    public ICut CreateCut()
    {
        var cut = new RoundCut();
        this.Cuts.Add(cut);

        return cut;
    }
}

public class SquareRoll : IRoll
{
    public IEnumerable<ICut> Cuts { get; private set; }

    public SquareRoll ()
    {
        this.Cuts = new List<ICut>();
    }

    public ICut CreateCut()
    {
        var cut = new SquareCut();
        this.Cuts.Add(cut);

        return cut;
    }
}

IRoll roll = new RoundRoll();
var cut = roll.CreateCut();
cut.DoSomething();

更新資料

如果SquareCut和RoundCut有很多不常用的方法,您仍然可以檢查ICuts具體類型,然后強制轉換為它:

IRoll roll = new RoundRoll();
var cut = roll.CreateCut();

if (cut is RoundCut) {
    (cut as RoundCut).RoundCutSpecificMethod();
}
else if (cut is SquareCut) {
    (cut as SquareCut).SquareCutSpecificMethod();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM