2015-06-03 26 views
0

我需要類的受保護屬性版本。這意味着外部類不能改變值,但是固有類可以。僅適用於非固有類的類的只讀版本

這裏是一個示例代碼,正如你所看到的,我使用的是「臭布爾解決方案」。我應該如何以更優雅的方式做到這一點?我希望這個問題有一些很好的模式解決方案。

EDIT由於大量的「保護套」的答案:

這樣做,我會無法設置非固有類的類屬性和構造函數的過程IsReadOnly屬性和價值將是無用的。

public class Foo1 
{ 
    protected bool smellyBoolSolution = false; 

    public bool IsReadOnly { get; private set; } 

    private int x; 

    public int X 
    { 
     get { return x; } 
     set 
     { 
      CheckCanWrite(); 
      x = value; 
     } 
    } 

    public Foo1(bool isReadOnly) 
    { 
     IsReadOnly = isReadOnly; 
    } 

    private void CheckCanWrite() 
    { 
     if (IsReadOnly && !smellyBoolSolution) 
      throw new InvalidOperationException("Class is read only."); 
    } 
} 

public class Foo2 : Foo1 
{ 
    public Foo2() 
     : base(true) 
    { 
    } 

    public void DoStuff() 
    { 
     int newX = 1; 
     //.... calculates new x 

     //Oh, using the smelly bool solution I can change my base class properties 
     base.smellyBoolSolution = true; 
     base.X = newX; 
     base.smellyBoolSolution = false; 
    } 
} 

//Usage 
public class Foo3 
{ 
    public void DoStuff() 
    { 
     //Foo1 in writable version 
     Foo1 f = new Foo1(false); 
     f.X = 1; 

     //Foo2 inherents Foo1 and only Foo2 can change X 
     Foo2 f2 = new Foo2(); 
     f2.X = 1; //Exception here. 
    } 
} 
+0

你的問題是什麼? –

+0

你的第一個陳述描述了「私人」......爲什麼你需要更多的東西? –

+0

IsReadOnly可能爲false,所以其他類可以將此對象用作可寫的版本。 – Pedro77

回答

1

使用受保護的領域,以實現從基礎寫作和繼承類,公開公共只讀屬性:

public class A 
{ 
    protected string FooField; 
    public string Foo { get { return FooField; } } 

    public A() 
    { 
     FooField = "A"; 
    } 
} 

public class B : A 
{ 
    public B() 
     : base() 
    { 
     FooField = "B"; 
    } 
} 

你甚至可以做,使用自動屬性:

public class A 
{ 
    public string Foo { get; protected set; } 

    public A() 
    { 
     Foo = "A"; 
    } 
} 

public class B : A 
{ 
    public B() 
     : base() 
    { 
     Foo = "B"; 
    } 
} 

另見Restricting Accessor Accessibility (C# Programming Guide)

+0

如果我將IsReadOnly設置爲false,該怎麼辦?我將無法將該類用作非固有類的可寫版本。 – Pedro77

+1

與您的陳述相矛盾,即只有繼承類應該能夠編寫這些屬性。下定決心。 – CodeCaster

+0

僅當IsReadOnly == true時。我做到了。 – Pedro77

0
private int x 
int X 
{ 
    public get { return x; } 
    protected set { x = value; } 
} 

,甚至更短的

int X { public get; protected set; } 

這兩個解決方案是不完全一樣的,因爲第一個使用明確實現的屬性,第二個自動完成的。

+2

我不會考慮你發佈的兩個解決方案是一樣的。一個使用自動實現的屬性,另一個具有明確實現的屬性。是的,在這種情況下,他們可能工作相同,但他們不一樣。你一定要包含描述如此的信息。 –

+0

@EBrown好點,我不打算寫xs小。修復它與編輯。 –

+0

@TimPohlmann沒有**不能修正任何事情,事實上它做了相反的事情,並且**不是**我所說的。 –

0

你要做的是違反Liskov substitution principle,應該避免。

通過繼承Foo1Foo2類承諾堅持接口超類Foo1公開。即在Foo1上運行的方法不必關心接收到的輸入是否爲Foo1Foo2。這兩種類型都暴露相同的界面,因此可以統一運行。

這就是爲什麼沒有優雅的解決方案,除了重新考慮你的設計問題。

相關問題