Ограничение доступа к методу в защищенном разделе несколькими классами - PullRequest
5 голосов
/ 07 июня 2010

Я хочу ограничить доступ защищенных методов только к определенным унаследованным классам.

Например, есть базовый класс, такой как

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;

Тогда возможно ли только доступ Method1, Method2 и Method3 , когда я использую объекты TDerived1 и Method3 и Method4 , когда я использую объекты TDerived2

Ответы [ 6 ]

7 голосов
/ 07 июня 2010

Нет способа сделать это. Если метод защищен , то все классы-потомки имеют к нему доступ. Возможно, вы захотите переосмыслить дизайн своего класса, если у вас есть два отдельных набора функций, которые можно легко разделить.

3 голосов
/ 07 июня 2010

Я бы разделил их, как ответ Джероена :

  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;

Из того, что вы описываете, это, кажется, лучше моделирует ваши требования, чем "монолитный" базовый класс (например, Мейсон уже написал ).

1 голос
/ 07 июня 2010

Мне кажется, ваши методы не объявлены в нужном месте.

Если Method1 и Method2 не вызываются в TBase и должны вызываться только из TDerived1 и потомков ... тогда эти методы должны быть объявлены в TDerived1.

Если у Method1 / 2 есть доступ к закрытым полям TBase, у вас должны быть свойства или методы Getter / setter для этих полей в TBase.

Но если вы не укажете более конкретные причины, почему эти методы должны быть объявлены в TBase, я бы сказал, что объявлять их там просто нехорошо.

1 голос
/ 07 июня 2010

Еще один способ - вы можете сделать это с помощью интерфейсов ...

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 голос
/ 07 июня 2010

Решение, которое работает аналогичным образом для публикации личных / защищенных / открытых свойств, которое работает для методов.
Таким образом, вы можете сделать это следующим образом:

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. Этот только работает, если TBase, TBase1 и TBase2 находятся в одном блоке.
  2. Это хак, работающий вокруг потенциально слабого класса,поэтому обязательно ознакомьтесь с дизайном своего класса

- jeroen

0 голосов
/ 08 июня 2010

хорошо ... Вот возможный способ достичь того, что вы ищете. Я думаю, что это требует 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...