2014-11-01 33 views
1

比方說,我有一個抽象基類正確使用C#「新」改性劑,使受保護的財產公開

public abstract class BaseClass 
{ 
    private MyObject myObject; 

    protected MyObject PropA 
    { 
     get 
     { 
      if(myObject == null) this.myObject = new MyObject(); 
      return this.myObject; 
     } 
    } 
} 

...這在我的派生類之一,我想使保護基類屬性PropA公衆。在這種情況下使用new modifier是否正確?

public class DerivedClass : BaseClass 
{ 
    public new MyObject PropA 
    { 
     get 
     { 
      return base.PropA; 
     } 
    } 
} 
+3

這並非非常錯誤。爲什麼你不能在基類中公開它是很難猜測的。也許只有一個BaseClass引用的客戶端程序員會陷入麻煩。 – 2014-11-01 22:24:14

+0

那麼,它的技術上是正確的,但乍一看,它似乎是一個可疑的設計。爲什麼'PropA'保護如果它可以在某些派生類中公開?爲什麼不開始公開?是什麼讓公共'PropA'成爲其他派生類中糟糕的設計? – InBetween 2014-11-01 23:01:19

回答

0

這是正確的。任何時候,如果您有一個成員與繼承類中的成員具有相同名稱的類,則需要使用new關鍵字(即使這兩個屬性/方法具有不同的返回類型)。

3

在這種情況下使用新修飾符是否正確?

技術上 - 是的,不會有錯誤或警告。

至於我,使用新的關鍵字本身作爲修飾符表示設計缺陷。

我舉一個例子。

public class MyList<T> : List<T> 
{ 
    public int AddCallsCount; 
    public new void Add(T t) 
    { 
     AddCallsCount++; 
     base.Add(t); 
    } 
} 

[TestClass] 
public class Test 
{ 
    [TestMethod] 
    public void TestThatsNotGood() 
    { 
     List<object> list = new MyList<object>(); 
     list.Add(1); 
     list.Add(2); 

     MyList<object> myList = list as MyList<object>; 

     Assert.AreEqual(0, myList.AddCallsCount); 

    } 
} 

它看起來像多態性的作品,但實際上並沒有。

更新: 好吧,有一個非常簡單的解釋。我省略了多態性是什麼的解釋。

通過實施abstract\virtualoverriding方法實現多態性。只要沒有指定virtualoverride修飾符MyList<T>.Add只是另一種「常見」公共方法。並與MyList<T>繼承List<T>,MyList<T>.Add'隱藏'List<T>.Add,因爲兩個方法的名稱和參數是相同的。

在較低的水平:一旦方法AddList<T>類型定義沒有標記virtual關鍵字,編譯器將不搜索重寫實際實例類型的方法(MyList<T>在這種情況下,某些),用於給定類型的變量(在這種情況下爲List<T>)。

定義它可能導致類API的邏輯錯誤和不正確的使用。

因此,編譯器'認爲'可能存在邏輯錯誤或設計缺陷並警告程序員。該new關鍵字只是一個交談的編譯器

方式是的,我知道這是不好的,但我需要它,因爲我的糟糕設計

+0

這將有助於解釋爲什麼(和哪裏)多態性(令人驚訝地)失敗。另外,從'List '繼承'可以說[*不是一個好主意](http://stackoverflow.com/a/5376343/1497596)。 – DavidRR 2014-11-01 23:31:39

+0

@DavidRR,您可以將列表更改爲SomeBaseClass和MyList 以SomeDerivedClass。沒關係。列表示例很自然,這是我第一次想到。 – 2014-11-01 23:43:25

2

如果您想在與基類中的成員具有相同名稱的派生類中添加成員,那麼new關鍵字的工作原理是正確的;然而,這種設計似乎違背了抽象類的目的。使PropA公開和虛擬在基類或公共和抽象:

public abstract class BaseClass 
{ 
    // Property not implemented here. 
    public abstract MyObject PropA { get; } 

    private MyObject _propB; 
    // Property implemented, but implementation can be overridden in derived class. 
    public virtual MyObject PropB 
    { 
     get { return _propB ?? (_propB = new MyObject()); } 
    } 

    public int PropC { get { return 5; } } 
} 

public class DerivedClass : BaseClass 
{ 
    // You must provide an implementation here. 
    private MyObject _propA; 
    public override MyObject PropA 
    { 
     get { return _propA ?? (_propA = new MyObject()); } 
    } 

    // You are free to override this property and to provide an new implementation 
    // or to do nothing here and to keep the original implementation. 
    public override MyObject PropB 
    { 
     get { return <new implementation...>; } 
    } 

    // PropC is inherited as is and is publicly visible through DerivedClass as well. 
}