2010-06-07 83 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。