2009-07-20 131 views
1

子類可以訪問父類中的受保護函數,但父類不能訪問子類中的受保護函數。如何訪問子類中的函數?

我想保持兩個類儘可能私有。父類是一種形式,只有一次使用實例。子類中的所有函數都是靜態的,它從父類繼承。

如何從父類訪問子類中的非公共靜態方法(在另一個單元中)?

編輯:

父類(第一部):

interface 

type 
TParent = class 
    public 
    procedure Initialize; 
    protected 
    procedure Test; virtual; 
end; 

implementation 

procedure TParent.Initialize; 
begin 
    Writeln('Initializing'); 
    Test; 
end; 

procedure TParent.Test; 
begin 

end; 

子類(第二單元):

interface 

uses 
ParentClass; 

type 
TChild = class(TParent) 
protected 
    procedure Test;override; 
end; 

implementation 

procedure TChild.Test; 
begin 
    Writeln('Test!'); 
end; 

代碼(第三單元):

var c:TParent; 

begin 
    try 
    c := c.Create; 
    c.Initialize; 
    c.Free; 
    Readln; 
end; 

輸出只是「初始化」。我試圖調試它,它沒有達到子類。

+0

它永遠不會因爲你是創建類錯到達子類。將您的創建更改爲讀取C:= TChild.Create,它將起作用。 – skamradt 2009-07-20 19:02:01

+0

您正在實例化該類錯誤。我想你之前已經被告知過。編譯器在你調用`c.Create`時沒有警告你?如果你想創建`TChild`的實例,那麼你需要調用該類的構造函數*:`TChild.Create`。 – 2009-07-20 19:30:30

回答

3

實際上有幾種方法可以做到這一點,在你的父類中,創建你調用的虛擬方法,但這些方法什麼都不做。在你的子類中,重寫這些方法。這些方法可以很容易地得到保護,但它們必須存在於父項中。

type 
    TParent = class 
    protected 
    procedure SpecialProcessing; virtual; 
    public 
    procedure DoWork; 
    end; 

    TChild = class(TParent) 
    protected 
    procedure SpecialProcessing; override; 
    end; 

procedure TParent.DoWork; 
begin 
    SpecialProcessing; 
end; 

procedure TParent.SpecialProcessing; 
begin 
    // does nothing, placeholder 
end; 

procedure TChild.SpecialProcessing; 
begin 
    // do special work here 
end; 

我故意沒做TParent。SpeciallProcessing摘要。這可以完成,但只有當TParent永遠不會被直接創建,只有後代纔會。抽象方法是一種未實現的方法,但被用作佔位符以供後來的孩子使用。

要創建使用實例如下:

var 
    C : TParent; 
begin 
    // Create as a TChild, which is a TParent decendant 
    C := TChild.Create; 
    try 
    C.DoWork; 
    finally 
    C.Free; 
    end; 
end; 
2

這是不可能的。在子類中使用非公共方法的全部目的是防止類(除了子類)能夠訪問它們。試圖解決這個問題違反了基本的面向對象的原則。

我會考慮重新考慮你的設計。

+0

如果您刪除了答案的第一句話,那麼我會進行最後的投票 - 顯然,這些限制的解決方法非常有限。你的(優秀的)主要觀點是這種機械化是一個跡象,表明存在設計問題。 – Argalatyr 2009-07-20 20:22:33

+0

有設計解決方法來解決需要做到這一點,但沒有辦法從父類中(這是原始問題)直接訪問子類中的私有靜態方法 - 因此我的評論是,這不是可能。 – 2009-07-20 20:28:51

3

你想做什麼違反了繼承原則Liskov Substitution。這可能有更好的方法。你到底想做什麼?

編輯:

你爲什麼不能創建子類的對象實例。您始終可以將其分配給父類類型的變量。這通常以工廠模式完成。

0

您可以通過在創建子類時使用某種回調(父類爲cattr,子類在定義時設置)來註冊子類。

雖然這很少是正確的做法。像其他人所說,考慮一種不同的模式。

我不是德爾福的編碼器,但你可以在父類上設置一個公共靜態變量,並從子類中的設置方法中設置它。

在某些情況下(希望將消息傳遞給各種子類上的類設置方法),這是有道理的,但可能有更好的方法來執行您所需的操作。您可能希望更多地瞭解您的代碼正在解決的問題。

1

我可能會丟失給誰已經回答了人們一些東西明顯。但我認爲這只是一個實例化正確對象的問題。

父代碼將調用子代碼,因爲該對象是子類的實例。

試試這個

var c:TChild; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end. 

甚至

var c:TParent; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end.