2012-03-16 17 views
1

我在這裏有一個面向對象的問題。我有兩個具有共同屬性和特定屬性的會話。我創建了一個基類並封裝了所有常用屬性/方法。 兩個會話有一個名爲Ranges的公共類型,它們又具有公共屬性和會話的特定屬性。因此,我認爲我可以在這種情況下編程爲超類型,並在運行時構建實例。編程到超類型的c#

public class Level 
{ 
    private readonly Ranges _range; 

    public Level(Ranges range) 
    { 
     _range = range; 
    } 

    public Ranges Range 
    { 
     get { return _range; } 
    } 

    public void CommonMethod() 
    { 
     throw new NotImplementedException(); 
    } 

    public int CommonProperty; 
} 

public class ALevel : Level 
{ 
    public ALevel() 
     : base(new ARange()) 
    { 

    } 

    public int ALevelProperty; 
} 

public class BLevel : Level 
{ 
    public BLevel() 
     : base(new BRange()) 
    { 

    } 

    public int BLevelProperty; 
} 

public class Ranges 
{ 
    public int CommonRangeProperty; 
} 

public class ARange : Ranges 
{ 
    public int ARangeProperty; 

    public ARange() 
    { 

    } 
} 

public class BRange : Ranges 
{ 
    public int BRangeProperty; 
} 

public class ASession 
{ 
    public ASession() 
    { 
     Level = new ALevel(); 
    } 

    public ALevel Level { get; set; } 
} 

public class BSession 
{ 
    public BSession() 
    { 
     Level = new BLevel(); 
    } 

    public BLevel Level { get; set; } 
} 

當我創建會話對象時,它不包含ASession的特定Ranges屬性。 我只能訪問基類的屬性 aSession.Level.Range.CommonRangeProperty = 1; 但我無法訪問aSession的特定屬性 aSession.Level.Range.ARangeProperty。

我在這裏做錯了什麼?

public class Test 
{ 
    public static void Main(string[] args) 
    { 
     ASession aSession = new ASession(); 

     aSession.Level.Range.CommonRangeProperty = 1; 
     //Not able to see ARangeProperty 

    } 
} 

回答

3

這是很簡單的:

LevelRangeRanges類型(而不是具體的ARange也不BRange)。 你應該使用泛型工作,如:

public abstract class Level<TRange> 
    where TRange : Ranges 
{ 
    private readonly TRange _range; 
    protected Level(TRange range) 
    { 
     this._range = range; 
    } 
    public TRange Range 
    { 
     get 
     { 
      return this._range; 
     } 
    } 
} 

public class ALevel : Level<ARange> 
{ 
    public ALevel() 
     : base (new ARange()) 
    { 
    } 
} 

你甚至可以進一步利用這個例子:

public abstract class Level<TRange> 
    where TRange : Ranges/*, new()*/ // i'm not sure about the new() ... have no compiler access right now to check! 
{ 
    private readonly TRange _range = new TRange(); 
    public TRange Range 
    { 
     get 
     { 
      return this._range; 
     } 
    } 
} 

public class ALevel : Level<ARange> 
{ 
} 

我們,你可以在ALevel引進另一名成員,像這樣:

public class ALevel : Level 
{ 
    public ARange ARange; 
} 

您可以通過使虛擬Range並重寫Range(使用redirec t到具體的水平ARangeBRange)。

它在很大程度上依賴於事後的使用... 如果您需要在proprety RangeRanges你應該引入另一個基類(沒有通用的限制)通用接入引進基座部件,您可以在您的通用覆蓋基類。所以你可以投的ALevel一個實例Level(W/O的基類,你將不得不轉換爲Level<TRange>混凝土TRange的知識,)...

+0

哇! Ur解決方案簡單而強大。謝謝!但是,你能解釋我的代碼問題嗎? – sundar 2012-03-16 06:43:06

+0

@sundar我試着用我的第一句話來解釋,「你的班級設置範圍類型爲範圍(不是具體的ARange或者BRange)」 - 這一點清楚嗎? – 2012-03-16 06:45:03

+0

但範圍是超類型,所以我應該能夠爲它分配派生類型。 – sundar 2012-03-16 06:47:47

1

如果我正確理解你的問題,你需要使用泛型去做你正在努力完成的事情。您的代碼將看起來像

public class Level<TRange> 
    where TRange: Ranges 
{ 
    private readonly TRange _range; 

    public TRange Range 
    { 
     get 
     { 
      return this._range; 
     } 
    } 
} 

public class ALevel : Level<ARange> 
{ 

} 

然後超類將能夠使用範圍爲基類型和派生類就可以使用它作爲自己的具體類型。

+0

'ALevel'由於'private'可見性而無法訪問'Level._range'。你應該至少將'_range'標記爲受保護的 - 或者引入一個受保護的獲取屬性 – 2012-03-16 06:48:13

+0

@AndreasNiedermair好抓...固定 – Yaur 2012-03-16 06:53:37

+0

不客氣! – 2012-03-16 06:58:01