2010-06-07 6 views
5

Quiero limitar el acceso de los métodos protegidos solo a ciertas clases heredadas.Limitar el acceso al método en la sección protegida a pocas clases

Por ejemplo, hay una clase base como

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

He dos clases derivadas de 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; 

Entonces es posible acceso sólo Método1, Método2 y metodo3 cuando i utilizar objetos de TDerived1 y Método3 y Método4 cuando iu Se objetos de TDerived2

Respuesta

7

No hay forma de hacerlo. Si un método es protected, todas las clases descendientes tienen acceso a él. Es posible que desee replantear el diseño de su clase si tiene dos conjuntos separados de funciones que pueden dividirse tan fácilmente.

1

Una solución que funciona de manera similar para publicar propiedades privadas/protegidas/públicas que funcionan por métodos.
por lo que podría hacerlo de esta manera:

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. 

Notas:

  1. Este sólo funciona siTBase, TBase1 y TBase2 están en la misma unidad.
  2. Se trata de un truco de trabajo en torno a un diseño de clase potencialmente débil, así que asegúrese de revisar su diseño de la clase

--jeroen

+1

¿Sugiere que simplemente "redeclar" un método en la declaración de clase promueve su visibilidad? Esto no funciona para mí en D2007 - Tengo que ** implementar ** un método de reenvío ** y ** el método tiene que estar protegido en la clase base, sin embargo. –

+1

Ese * tipo de * trabajo ... Si las clases se declaran en la misma unidad, puede usar ese método. Simplemente haga que TBase1.Method1 llame a "Method1 heredado". Pero no tiene sentido hacerlo. Todavía mal diseño en mi humilde opinión. –

+0

@Ulrich: edité la publicación con un ejemplo más elaborado. @Ken: Totalmente de acuerdo, de ahí las notas que agregué en el edito. –

3

que habíamos separado de ellos, similar a 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; 

Según lo que describe, esto parece modelar mejor sus requisitos que una clase base "monolítica" (como Mason already wrote).

+0

+1. Esto es exactamente lo que quise decir sobre repensar el diseño de la clase. –

+0

Puede realizar este rediseño solo si Method1 y Method2 no dependen de Method3 y Method4 (y viceversa); por lo tanto, no lo rediseñé :-) –

+0

Sí, por supuesto. Las posibilidades exactas dependen de la situación exacta. :-) –

1

una forma más - usted puede hacer esto utilizando Interfaces ...

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

Me parece que sus métodos no se declaran en el lugar correcto.

Si Método1 y Método2 no son llamados en TBase, y solo deben invocarse desde TDerived1 y descendientes ... entonces esos métodos deben declararse en TDerived1.

Si Method1/2 accede a campos privados de TBase, entonces debe tener propiedades o Getter/setter a esos campos en TBase.

Pero a menos que proporcione razones más específicas sobre por qué esos métodos deben declararse en TBase, diría que es un mal diseño declararlos allí.

0

ok ... Aquí hay una manera posible de lograr lo que estás buscando.Creo que requiere Delphi 2005 o posterior sin embargo. (O lo que sea la versión que introdujo el "Estrictamente Protegida | privada" visibilidad)

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; 

Y los métodos de este aspecto

procedure TDerived2.Method3; 
begin 
    inherited Method3; 
end; 

Pero sus requisitos hacen que me pregunte si su método realmente pertenece a la clase Tbase . Parece que deberían ser un procedimiento estático, o tal vez un procedimiento de clase de otra clase. No creo que realmente pertenezcan a TBase.

Cuestiones relacionadas