Далеко не всегда парадигма членов класса private/protected/public работает так как хотелось бы.
Ведь на самом деле у класса бывают "обычные" пользователи, "продвинутые" пользователи и "эксперты".
Каждому классу пользователей иногда хочется дать "свой уровень доступа" к методам проектного класса.
Я долго думал над тем как это сделать.
Конечно можно использовать интерфейсы. Не буду рассказывать как - думаю, что все и без меня всё прекрасно знают.
Но (!) интерфейсы это - накладные расходы на AddRef/Release.
А иногда эти накладные расходы хочется избежать.
Хочется что-то подобное интерфейсам, но без ARC. "Протоколы" так сказать.
Про "протоколы" вот ссылки:
Протоколы vs интерфейсы.
"Протоколы" на "коленке".
Objective-C и Delphi.
Массовое использование интерфейсов "вообще" и InterlockedIncrement/InterlockedDecrement в частности...
Не знаю уж как в Objective-C "методы зовутся по имени". Но если бы я это делал..
Но это всё - "конь в вакууме".
Как бы это сделать на практике?
Я долго думал и придумал вот какую штуку.
Ничего "космического". Просто сделать "фасадные" записи, которые имеют доступ к "кишкам объекта".
По "аналогии" с Enumerator'ами, которые тоже реализуются записями:
Про generic'и, "примеси", интерфейсы и енумераторы. Только код.
Товарищ написал. "К слову про синтаксический сахар".
Примерно так:
https://bitbucket.org/lulinalex/mindstream/src/b550da2431d733e50aab7b5bb3c4dcca7f3f68aa/Examples/Protocols/Protocols.dpr?at=B284&fileviewer=file-view-default
Вот как-то так..
Понятное дело, что "для каждого класса" такое делать "нудно", да и "глупо".
Но когда класс - "сложный" и выполняет "несколько ответственностей", то это может оказатья полезным.
Ну и про KISS и SRP - я конечно знаю.
(+) Про RTTI и helper'ы я конечно знаю. Тоже.
(+)(+) И про God-object - тоже.
Ведь на самом деле у класса бывают "обычные" пользователи, "продвинутые" пользователи и "эксперты".
Каждому классу пользователей иногда хочется дать "свой уровень доступа" к методам проектного класса.
Я долго думал над тем как это сделать.
Конечно можно использовать интерфейсы. Не буду рассказывать как - думаю, что все и без меня всё прекрасно знают.
Но (!) интерфейсы это - накладные расходы на AddRef/Release.
А иногда эти накладные расходы хочется избежать.
Хочется что-то подобное интерфейсам, но без ARC. "Протоколы" так сказать.
Про "протоколы" вот ссылки:
Протоколы vs интерфейсы.
"Протоколы" на "коленке".
Objective-C и Delphi.
Массовое использование интерфейсов "вообще" и InterlockedIncrement/InterlockedDecrement в частности...
Не знаю уж как в Objective-C "методы зовутся по имени". Но если бы я это делал..
Но это всё - "конь в вакууме".
Как бы это сделать на практике?
Я долго думал и придумал вот какую штуку.
Ничего "космического". Просто сделать "фасадные" записи, которые имеют доступ к "кишкам объекта".
По "аналогии" с Enumerator'ами, которые тоже реализуются записями:
Про generic'и, "примеси", интерфейсы и енумераторы. Только код.
Товарищ написал. "К слову про синтаксический сахар".
Примерно так:
https://bitbucket.org/lulinalex/mindstream/src/b550da2431d733e50aab7b5bb3c4dcca7f3f68aa/Examples/Protocols/Protocols.dpr?at=B284&fileviewer=file-view-default
program Protocols;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TmyClass = class
public
// Дальше идут протоколы "для продвинутого пользователя":
type
Advanced1 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForAdvancedUser1;
procedure ForAdvancedUser2;
end;//Advanced1
Advanced2 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForAdvancedUser1;
end;//Advanced2
Advanced3 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForAdvancedUser2;
end;//Advanced3
// Дальше идут протоколы "для экспертов":
type
Expert1 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForExpertUser1;
procedure ForExpertUser2;
end;//Expert1
Expert2 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForExpertUser1;
end;//Expert2
Expert3 = record
private
f_Provider : TmyClass;
public
constructor Create(aProvider: TmyClass);
procedure ForExpertUser2;
end;//Expert3
private
procedure ForAdvancedUser1;
procedure ForAdvancedUser2;
procedure ForExpertUser1;
procedure ForExpertUser2;
public
procedure ForRegularUser1;
procedure ForRegularUser2;
public
// Далее идут методы для получения "протоколов"
function AsA1: Advanced1;
function AsA2: Advanced2;
function AsA3: Advanced3;
function AsE1: Expert1;
function AsE2: Expert2;
function AsE3: Expert3;
end;//TmyClass
// TmyClass.Advanced1
constructor TmyClass.Advanced1.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Advanced1.ForAdvancedUser1;
begin
f_Provider.ForAdvancedUser1;
end;
procedure TmyClass.Advanced1.ForAdvancedUser2;
begin
f_Provider.ForAdvancedUser2;
end;
// TmyClass.Expert1
constructor TmyClass.Expert1.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Expert1.ForExpertUser1;
begin
f_Provider.ForExpertUser1;
end;
procedure TmyClass.Expert1.ForExpertUser2;
begin
f_Provider.ForExpertUser2;
end;
// TmyClass.Expert2
constructor TmyClass.Expert2.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Expert2.ForExpertUser1;
begin
f_Provider.ForExpertUser1;
end;
// TmyClass.Expert3
constructor TmyClass.Expert3.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Expert3.ForExpertUser2;
begin
f_Provider.ForExpertUser2;
end;
// TmyClass.Advanced2
constructor TmyClass.Advanced2.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Advanced2.ForAdvancedUser1;
begin
f_Provider.ForAdvancedUser1;
end;
// TmyClass.Advanced3
constructor TmyClass.Advanced3.Create(aProvider: TmyClass);
begin
f_Provider := aProvider;
end;
procedure TmyClass.Advanced3.ForAdvancedUser2;
begin
f_Provider.ForAdvancedUser2;
end;
// TmyClass
procedure TmyClass.ForAdvancedUser1;
begin
WriteLn('ForAdvancedUser1');
end;
procedure TmyClass.ForAdvancedUser2;
begin
WriteLn('ForAdvancedUser2');
end;
procedure TmyClass.ForExpertUser1;
begin
WriteLn('ForExpertUser1');
end;
procedure TmyClass.ForExpertUser2;
begin
WriteLn('ForExpertUser2');
end;
procedure TmyClass.ForRegularUser1;
begin
WriteLn('ForRegularUser1');
end;
procedure TmyClass.ForRegularUser2;
begin
WriteLn('ForRegularUser2');
end;
function TmyClass.AsA1: Advanced1;
begin
Result := Advanced1.Create(Self);
end;
function TmyClass.AsA2: Advanced2;
begin
Result := Advanced2.Create(Self);
end;
function TmyClass.AsA3: Advanced3;
begin
Result := Advanced3.Create(Self);
end;
function TmyClass.AsE1: Expert1;
begin
Result := Expert1.Create(Self);
end;
function TmyClass.AsE2: Expert2;
begin
Result := Expert2.Create(Self);
end;
function TmyClass.AsE3: Expert3;
begin
Result := Expert3.Create(Self);
end;
var
l_C : TmyClass;
begin
try
l_C := TmyClass.Create;
try
l_C.ForRegularUser1;
l_C.ForRegularUser2;
l_C.AsA1.ForAdvancedUser1;
l_C.AsA1.ForAdvancedUser2;
l_C.AsA2.ForAdvancedUser1;
l_C.AsA3.ForAdvancedUser2;
l_C.AsE1.ForExpertUser1;
l_C.AsE1.ForExpertUser2;
l_C.AsE2.ForExpertUser1;
l_C.AsE3.ForExpertUser2;
finally
FreeAndNil(l_C);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Вот как-то так..
Понятное дело, что "для каждого класса" такое делать "нудно", да и "глупо".
Но когда класс - "сложный" и выполняет "несколько ответственностей", то это может оказатья полезным.
Ну и про KISS и SRP - я конечно знаю.
(+) Про RTTI и helper'ы я конечно знаю. Тоже.
(+)(+) И про God-object - тоже.
Комментариев нет:
Отправить комментарий