Ограничение доступа метода в защищенном разделе к немногим классам

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

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

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

5
задан Bharat 8 June 2010 в 05:38
поделиться

6 ответов

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

7
ответ дан 18 December 2019 в 14:42
поделиться

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

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
ответ дан 18 December 2019 в 14:42
поделиться

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

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

1
ответ дан 18 December 2019 в 14:42
поделиться

ок... Вот возможный способ достичь того, что вы ищете. Я думаю, что для этого требуется Delphi 2005 или более поздняя версия. (Или любая другая версия, в которой появилась видимость "Strict Protected|private")

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.

0
ответ дан 18 December 2019 в 14:42
поделиться

Я бы разделил их, подобно ответу Йеруна :

  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;

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

3
ответ дан 18 December 2019 в 14:42
поделиться

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

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

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

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

1
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: