Я хочу ограничить доступ защищенных методов для определенных наследованных классов только.
Например, существует базовый класс как
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
Нет возможности сделай это. Если метод защищен , то все классы-потомки имеют к нему доступ. Возможно, вы захотите переосмыслить дизайн своего класса, если у вас есть два отдельных набора функций, которые можно легко разделить.
Еще один способ - вы можете сделать это с помощью интерфейсов ...
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;
Решение, которое работает аналогичным образом для публикации частных / защищенных / общедоступных свойств, которые работают для методов.
Вы можете сделать это так:
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.
Примечания:
TBase
, TBase1
и TBase2
являются в том же блоке. - jeroen
ок... Вот возможный способ достичь того, что вы ищете. Я думаю, что для этого требуется 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.
Я бы разделил их, подобно ответу Йеруна :
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;
Судя по тому, что вы описываете, это, кажется, лучше моделирует ваши требования, чем «монолитный» базовый класс ( как Мейсон уже писал ).
Мне кажется, что ваши методы объявлены не в нужном месте.
Если Method1 и Method2 не вызываются в TBase и должны вызываться только из TDerived1 и потомков ...тогда эти методы должны быть объявлены в TDerived1.
Если Method1 / 2 обращается к частным полям TBase, тогда у вас должны быть свойства или Getter / setter для этих полей в TBase.
Но если вы не укажете более конкретные причины того, почему эти методы должны быть объявлены в TBase, я бы сказал, что объявлять их там - просто плохой дизайн.