[英]Can I subclass a abstract class which has another abstract class which is also subclassed? (C#)
[英]C# Abstract class has another abstract class object
我很少代表一些測量數據的類,起初, ICut
抽象類具有派生的RoundCut
和SquareCut
如下所示:
public abstract class ICut
{
}
public class RoundCut : ICut
{
DoSomeWithRoundCut(){}
}
public class SquareCut : ICut
{
DoSomeWithSquareCut(){}
}
當然,它包含一些實現,但是對於這個問題並不重要。 ICut
是抽象類而不是接口,因為它本身具有一些實現。
然后,這是代表ICut
數據集的類,再次基於抽象IRoll
以及派生的RoundRoll
和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;
}
}
而現在,我當然無法通過調用例如以下SquareCut
直接達到RoundCut
或SquareCut
額外實現:
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
不再是RoundRoll
和SquareRoll
的通用接口,因此您無法創建紙卷集合。
可以通過在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.