2009-04-23 104 views
6

這可能是一個初學者問題,但是有沒有一種標準的方法來將Wheel屬性的重複重構爲抽象類,但仍然將明確的類型轉換爲Part類型。假設我們必須防止將FastCarWheel放在SlowCar上,並且有很多屬性就像這個一樣。重構抽象類的基本問題

abstract class Car {} 

class FastCar : Car 
{ 
    public FastCarWheel Wheel { get; set; } 
} 

class SlowCar : Car 
{ 
    public SlowCarWheel Wheel { get; set; } 
} 

abstract class WheelPart {} 

class FastCarWheel: WheelPart {} 

class SlowCarWheel: WheelPart {} 

在這種情況下,通常只允許這種類型的重複?我正在考慮使用泛型,但似乎我正在解決這個問題,並且對於每個以這種方式運行的其他屬性都會變得更糟。

abstract class Car <P> 
    where P : Part 
{ 
    protected abstract P Wheel { get; set; } 
} 

感謝

回答

0

定義輪接口(IWheel):

public interface IWheel 
{ 
} 

實施FastCarWheel和SlowCarWheel的接口,例如

public class FastCarWheel : IWheel 
{ 
} 

現在你的抽象類變爲:

汽車的

子類就可以自由使用他們選擇的任何輪的實現:

FastCar fastCar = new FastCar(); 
fastCar.Wheel = new FastCarWheel(); 
+0

這就是問題所在。他不希望任何汽車有任何類型的車輪。他希望FastCars只有FastWheels,而SlowCars只有SlowWheels。一個接口不會完成這個。 – Joseph 2009-04-23 18:16:04

+0

如果FastCar不能具有SlowCarWheel,那麼該邏輯屬於FastCar,而不屬於基類。 – 2009-04-23 18:22:42

1

我想用FastSlowpolicy可以幫助把正確的車輪對於給定的車型(其中兩個CarWheel取決於該政策,並且物體具有私人聚合的輪子)。

1

這種解決方案並不多態的,但如果你在基類水平需要知名度可能是你唯一的選擇:

abstract class Car 
{ 
    private CarWheel wheel; 
    public CarWheel Wheel 
    { 
     get { return wheel; } 
     protected set { wheel = value; } 
    } 
} 

class FastCar : Car 
{ 
    public new FastCarWheel Wheel 
    { 
     get { return base.Wheel as FastCarWheel; } 
     set { base.Wheel = value; } 
    } 
} 

class SlowCar : Car 
{ 
    public new SlowCarWheel Wheel 
    { 
     get { return base.Wheel as SlowCarWheel ; } 
     set { base.Wheel = value; } 
    } 
} 

你可能想,如果你的基類是做太多評價。通過將你的課程分成許多小班來解決你的問題是可能的。另一方面,有時這是不可避免的。

1

我會創造一個ICAR,然後定義您的汽車那樣,而不是一個抽象類

interface ICar 
{ 
    IWheel Wheel {get; set;} 
} 

class FastCar: ICar 
{ 
    FastWheel fastWheel; 
    IWheel Wheel 
    { 
     get { return fastWheel; } 
     set 
     { 
      if (value is FastWheel) fastWheel = (FastWheel)value; 
     }  
    }   
} 

class SlowCar: ICar 
{ 
    SlowWheel slowWheel; 
    IWheel Wheel 
    { 
     get { return slowWheel; } 
     set 
     { 
      if (value is SlowWheel) slowWheel = (SlowWheel)value; 
     }  
    } 
} 

class FastWheel: IWheel {} 
class SlowWheel: IWheel {} 
1

因爲你的目標似乎是允許客戶端代碼來獲取財產回爲一個WheelPart,但只將其設置爲特定的子類,您有幾個選項。雖然我擔心他們都不是很乾淨。

首先,如果錯誤類型設置,你可以拋出一個運行時錯誤:

public abstract class Car 
    { 
     public abstract WheelPart Wheel { get; set; } 
    } 

    public class FastCar : Car 
    { 
     private FastWheel _wheel; 
     public override WheelPart Wheel 
     { 
      get { return _wheel; } 
      set 
      { 
       if (!(value is FastWheel)) 
       { 
        throw new ArgumentException("Supplied wheel must be Fast"); 
       } 
       _wheel = (FastWheel)value; 
      } 
     } 
    } 

但我不會這麼做,因爲它是非常不清楚的客戶端代碼,任何其他類型的車輪將引發異常,他們將得不到編譯器反饋。

否則,你可以分離出getter和setter的屬性,以便需要的類型是很清楚的:

public abstract class Car 
    { 
     public abstract WheelPart Wheel { get; } 
    } 

    public class FastCar : Car 
    { 
     private FastWheel _wheel; 
     public override WheelPart Wheel 
     { 
      get { return _wheel; } 
     } 

     public void SetWheel(FastWheel wheel) 
     { 
      _wheel = wheel; 
     } 
    } 

這是更清晰的客戶端和恕我直言一個更好的解決方案,如果你絕對必須公開作爲基礎WheelPart類的吸氣劑。