2012-01-13 65 views
3

假設我們有3個類:Base,RootChild成員的繼承和知名度

public abstract class Base 
{ 
    protected int _Value; 

    public double DoSomeWork(int value) 
    { 
     _Value = value; 
     double result = Calculate(); 

     return result; 
    } 

    public abstract double Calculate(); 

    public Child CreateChild(int length) 
    { 
     return new Child(this); 
    } 
} 

public class Root : Base 
{ 
    public override double Calculate() 
    { 
     return _Value; 
    } 
} 

public class Child : Base 
{ 
    readonly Base _Container; 

    public Child(Base container) 
    { 
     _Container = container; 
    } 

    public override double Calculate() 
    { 
     double result = _Container.Calculate(); 
     // do some more calculation 

     return result; 
    } 
} 

我在這裏的問題是,我只喜歡DoSomeWork(和CreateChild)可以公開訪問,但在我的「架構」我被迫做出Calculate公也。還是我?

任何輸入將非常感激。

編輯:

Calculate不能使用,因爲這條線的Child

double result = _Container.Calculate(); 

這將導致發生生成錯誤保護。

+0

由於您的代碼看起來不完整,因此您不完全清楚您要完成的操作。例如,'_Value'字段不在任何地方使用,以及'DoSomeWork'方法中的'value'參數。展示它們應該如何交互會有所幫助。現在'DoSomeWork'顯得多餘,'Calculate'似乎在做所有的工作(因此需要公開)。另一方面,可能會發現「Calculate」根本不屬於這個類,這是我從第一眼看到的。 – Groo 2012-01-13 12:19:15

+0

@Groo _Value用於'Root'類。我已經編輯了「使用」'value'參數的問題。我同意這是最可能有錯的「架構」。一般的想法是,消費者應該實例化'Root'類,然後在使用'DoSomeWork'的同時用'CreateChild'生成子類。理想情況下,所有其他成員不應該是可見的。 (包括'Child' ctor) – clearpath 2012-01-13 12:31:37

+0

我已經更新了我的答案。 – Groo 2012-01-13 12:53:12

回答

6

不,您可以製作它protected。這樣你的派生類仍然可以訪問它並能夠覆蓋它,但它不會被公開。

好想法,這正是要做到這一點的方式:儘可能少地覆蓋並儘可能隱藏。

- 編輯 -

由於這是可能的,你實際上是在做什麼一個簡單的例子,我只能提供一個猜測一下這些方法做的,但在這裏不言而喻。

我有一種感覺,Calculate方法可能不屬於你的Base類。它看起來像提供了DoSomeWork使用的輔助計算結果。當你的基類有一些通用計算來「派發」派生類時,通常使用繼承,這樣你就不必重複自己。

例如,假設您的DoSomeWork方法具有某些不會更改的某些功能,但需要先執行「外部」計算。如果通過對外部計算機創建一個簡單的單獨的界面開始:

interface ICalculator 
{ 
    double Calculate(); 
} 

你可以定義此接口的不同實現。您可以通過創建一個簡單的實現(類似於您Root功能)開始:

class SimpleCalculator : ICalculator 
{ 
    readonly double _value; 
    public SimpleCalculator(double value) 
    { 
     _value = value; 
    } 

    public double Calculate() 
    { 
     return _value; 
    } 
} 

而且你還可以很容易地包裝現有的實現中更復雜的類(類似於CreateChild打算做):

// for the rest of the world, this is an ICalculator like any other 
class CalculatorWrapper : ICalculator 
{ 
    readonly ICalculator _base; 
    public CalculatorWrapper(ICalculator baseCalc) 
    { 
     _base = baseCalc; 
    } 

    public double Calculate() 
    { 
     double value = _base.Value; 
     return 2 * value; 
    } 
} 

然後,你實際類需要使用此功能,一些預期的「額外工作」:

interface MyWorker 
{ 
    double DoSomeWork(int value); 
} 

class YourClass 
{ 
    readonly ICalculator _calc; 
    readonly double _someOtherValue; 

    public YourClass(ICalculator calc, double someOtherValue) 
    { 
     _calc = calc; 
     _someOtherValue = someOtherValue; 
    } 

    public double DoSomeWork(int value) 
    { 
     // use whatever you get from your calc 
     double externalValue = _calc.Calculate(); 

     // and do some "actual work" 
     return _someOtherValue + value + externalValue; 
    } 
} 

或者,你可以通過「計算器」來DoSomeWork在每次調用,作爲參數,並更改複雜類的東西,如:

interface MyWorker 
{ 
    double DoSomeWork(ICalculator calc, int value); 
} 

class YourClass 
{ 
    public double DoSomeWork(ICalculator calc, int value) 
    { 
     // use whatever you get from your calc 
     double externalValue = calc.Calculate(); 

     // and do some "actual work" 
     return _someOtherValue + value; 
    } 
} 
+0

+1尤其是對「良好的想法」的評論。非常真實,值得指出。 – 2012-01-13 12:05:17

1

你可以聲明Calculateprotected,它會只有通過擴展課程才能訪問。

這是相同的概念protected int _Value; - 您可以訪問它在當前的類及其所有的孩子,而不是從外面。

1

它不應該是public。它可以製成protected

0

不正確......你不必做公益......你可以做受保護的,這意味着任何一個孩子派生類可以利用的功能,但它之外的不可見的其他控件。

0

您可以eigther使用protected(=只在類中,並在其繼承類中)或internal(=只能在同一組件內訪問)。見HERE

0

你可以把它:

  1. protected - 只有到從它派生類型的訪問。
  2. internal - 唯一可在同一組件類型(或強命名大會宣佈爲可以看到裝配內部的類型)。
  3. protected internal - 上述兩種的允許;同一個程序集中的派生類型和其他類型都可以訪問它。

.NET也有一些限制具有既派生類型和在同一程序的接入類型,但C#不支持它(大概是因爲你可以在這種情況下與internal獲得通過,並這將是一個棘手的想法,不容易與protected internal混淆)。

在這種情況下,應該幾乎肯定會protected

8

讓我們從你的榜樣刪除不必要的冗餘代碼:

public abstract class Base 
{ 
    public abstract double Calculate(); 
} 
public class Derived : Base 
{ 
    private Base b; 
    public override double Calculate() 
    { 
     double r = b.Calculate(); 
     // Perform additional calculations on r 
     return r; 
    } 
} 

問題是「不計算必須公開?「因爲私人虛函數是C#非法

計算不能是私有的。

計算不能被保護,因爲如果B不是在編譯時已知實例的衍生或更好派生調用b.Calculate()是非法的(原因是:受保護的成員可以被子類訪問;由b引用的對象可能是Base的完全不同的子類,並且Derived不允許訪問該類的受保護方法,因爲Derived不是從它派生的。)

計算可能是內部的,受保護的內部或公共。

但是,一種使計算受保護的方法。各地對保護接收器的規則,如果你想要做一個終端上運行被要求成爲一個更派生類型則讓基類做骯髒的工作,爲您

public abstract class Base 
{ 
    protected static double Calculate(Base b) 
    { 
     // perfectly legal inside Base: 
     return b.Calculate(); 
    }   
    protected abstract double Calculate(); 
} 
public class Derived : Base 
{ 
    private Base b; 
    protected override double Calculate() 
    { 
     double r = Base.Calculate(b); 
     // Perform additional calculations on r 
     return r; 
    } 
} 

有意義嗎?

+0

是的,它非常有用。但是,儘管從技術上講這是正確的答案,但我對Groos解決方案給出了答案,因爲它激發了對我的「架構」 – clearpath 2012-01-16 09:37:10