Далеко не всегда парадигма членов класса 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 - тоже.
Комментариев нет:
Отправить комментарий