2010-06-07 82 views
5

我想限制受保護的方法只能訪問某些繼承的類。將受保護的部分限制爲少數類的訪問

例如有一個基類等

TBase = Class 
    Protected 
    Method1; 
    Method2; 
    Method3; 
    Method4; 
End; 

我已經從TBASE

TDerived1 = Class(TBase) 
    //Here i must access only Method1,Method2 and Method3 
End; 

TDerived2 = Class(TBase) 
    //Here i must access only Method3 and Method4 
End; 

派生兩個類然後是有可能 訪問僅方法1,方法2和方法3當我使用TDerived1方法3和方法4當iu se對象TDerived2

回答

7

沒有辦法做到這一點。如果方法是受保護,則所有後代類都有權訪問它。如果您有兩套獨立的功能可輕鬆劃分,您可能需要重新考慮您的班級設計。

1

解決方案以類似的方式發佈適用於方法的私有/保護/公共屬性。
所以,你可以做這樣的:

unit PropertyAndMethodVisibilityPromotionUnit; 

interface 

type 
    TBase = class 
    private 
    procedure Method1; 
    procedure Method2; 
    procedure Method3; 
    procedure Method4; 
    end; 

    TBase1 = class(TBase) 
    protected 
    procedure Method1; 
    procedure Method2; 
    end; 

    TBase2 = class(TBase) 
    protected 
    procedure Method3; 
    procedure Method4; 
    end; 

    TDerived1 = class(TBase1) 
    //Here i must access only Method1 and Method2 
    end; 

    TDerived2 = class(TBase2) 
    //Here i must access only Method3 and Method4 
    end; 

implementation 

procedure TBase.Method1; 
begin 

end; 

procedure TBase.Method2; 
begin 

end; 

procedure TBase.Method3; 
begin 

end; 

procedure TBase.Method4; 
begin 

end; 

procedure TBase1.Method1; 
begin 
    inherited; 
end; 

procedure TBase1.Method2; 
begin 
    inherited; 
end; 

procedure TBase2.Method3; 
begin 
    inherited; 
end; 

procedure TBase2.Method4; 
begin 
    inherited; 
end; 

end. 

注:

  1. 如果只作品TBaseTBase1TBase2在同一個單位。
  2. 它是圍繞一個潛在的薄弱一流的設計工作黑客攻擊,因此務必仔細閱讀一流的設計

--jeroen

+1

你是否建議只在類聲明中「重新聲明」一種方法來提升其可見性?這在D2007中對我來說不起作用 - 我必須**實現一個轉發方法**並且**該方法必須在基類中受到保護。 – 2010-06-07 16:26:11

+1

* *種類*如果類在同一單元中聲明,則可以使用該方法。只需要TBase1.Method1調用「繼承Method1」。但這樣做毫無意義。 仍然不好的設計恕我直言。 – 2010-06-07 17:04:28

+0

@Ulrich:我用一個更詳細的例子編輯了這篇文章。 @Ken:完全同意,因此我在edito中添加的註釋。 – 2010-06-08 05:53:00

3

我會分裂他們,類似Jeroen's answer

TBase = class 
    end; 

    TBase12 = class(TBase) 
    protected 
    procedure Method1; 
    procedure Method2; 
    end; 

    TBase34 = class(TBase) 
    protected 
    procedure Method3; 
    procedure Method4; 
    end; 

    TDerived1 = class(TBase12) 
    end; 

    TDerived2 = class(TBase34) 
    end; 

從你的描述來看,這似乎比「單一」基礎類(比如Mason already wrote)更好地模擬你的需求。

+0

+1。這正是我重新思考課程設計的意思。 – 2010-06-07 16:56:25

+0

只有在Method1和Method2不依賴於Method3和Method4(反之亦然)時,纔可以執行此重新設計;因此我沒有重新設計它:-) – 2010-06-10 18:17:38

+0

是的,當然。確切的可能性取決於確切的情況。 :-) – 2010-06-10 21:31:20

1

另一種方式 - 你可以做到這一點使用接口...

IBase1 = interface 
    // press Ctrl+Shift+G here to generate your own sexy GUID 
    procedure Method1; 
    procedure Method2; 
end; 

IBase2 = interface 
    // press Ctrl+Shift+G here again 
    procedure Method3; 
    procedure Method4; 
end; 

TBase = class(TInterfacedObject, IBase1, IBase2) 
public 
    { IBase1 } 
    procedure Method1; 
    procedure Method2; 
    { IBase2 } 
    procedure Method3; 
    procedure Method4; 
end; 

var 
    B1: IBase1; 
    B2: IBase2; 
begin 
    B1 := TBase.Create as IBase1; 
    B2 := TBase.Create as IBase2; 

    B1.Method1; // works 
    B1.Method3; // Can't compile 

    B2.Method3; // works 
end; 
1

在我看來,你的方法不是在正確的地方聲明。

如果Method1和Method2沒有在TBase中調用,並且只能從TDerived1和派生類中調用...那麼這些方法應該在TDerived1中聲明。

如果Method1/2訪問TBase的私有字段,那麼您應該爲TBase中的這些字段設置屬性或Getter/setter。

但是,除非你給出更具體的理由說明爲什麼這些方法需要在TBase中聲明,否則我認爲在這裏宣佈它們只是一個糟糕的設計。

0

好的......這是一個可能的方法來實現你正在尋找的東西。但我認爲它需要Delphi 2005或更高版本。 (或任何介紹了「嚴格保護|私人」版本的知名度)

TBase = Class 
    Strict Protected 
    procedure Method1; 
    procedure Method2; 
    procedure Method3; 
    procedure Method4; 
End; 

TDerived1 = Class(TBase) 
    Protected 
    procedure Method1; 
    procedure Method2; 
    procedure Method3; 
End; 

TDerived2 = Class(TBase) 
    Protected 
    procedure Method3; 
    procedure Method4; 
End; 

TUserClass = class 
    FImplementer : TDerived1; 
end; 

而且方法是這樣的

procedure TDerived2.Method3; 
begin 
    inherited Method3; 
end; 

但是你的要求讓我懷疑你的方法真正屬於你的TBASE類。看起來它們應該是靜態過程,或者可能是另一個類的類過程。我不認爲他們真的屬於TBase。