Приховати public-метод у спадкоємці
Як можна приховати public-метод у спадкоємці класу? Наприклад, TStringList має 2 методи - Add і AddObject. Як зробити невидимим для спадкоємця метод Add?
У принципі ніяк не зробиш. Бо завжди можна закастити під предка і викликати метод
А якщо без наведення типів? Наприклад:
TGetList=class(TStringList) private function Add: Integer; reintroduce; end;
В цьому випадку мета досягається, але отримуємо хінт, що метод ніде не використовується.
Звуження області видимості неможливе. Якби це було можливим, то й поліморфізму не було б.
Ладно. Дякую всім. Буду Exception видавати у разі використання.
хм. Я, напевно, трохи ввів в оману. Хотів сказати - приховати в спадкоємці від спадкоємця.
TGetList=class(TStringList) private function Add: Integer; reintroduce; public constructor Create; end;
конструктор TGetList.Create; begin Add; end;
У принципі, якщо перенести метод у private-секцію, як заглушку і використовувати при виклику, наприклад, конструктора, то хінт видаватися не буде.
Адже користувач класу очікує, що метод працює за аналогією з батьківським класом. Хотілося б виключити будь-яку помилку.
А метод у [6] не підійде?
function Add: Integer; virtual; abstract; reintroduce;
Якщо вийде, то ти матимеш новий ланцюжок успадкування і водночас абстрактний метод, який приховує метод предка.
А шкода, я так сподівався. Ну, тоді без abstract
Вибачаюсь за можливу грубість.
> У цьому випадку мета досягається, але отримуємо хінт Чи, а не пофігу на той хінт?
> В принципі, якщо перенести метод у private-секцію, як заглушку > і використовувати при виклику, наприклад, конструктора, хінт > видаватися не буде
Дався тобі цей хінт. Хінти – звичайна справа. Наприклад при будь-якому використанні PChar дельфі лається - unsafe type. У нас своя голова за плечима :)
У мене перед релізом не лишається хінтів у програмі.
Ясно, значить справа принципу і Pointer ви ніколи не використовуєте і PChar?
А як же вдається використовуючи Pointer і PChar уникати всіх hint??
const Someconst : PChar = "А ось і хінт";
type TSomerecord = Record Addr: Pointer; // А ось і другий хінт . End;
Someproc = Procedure(Addr:Pointer); // третій хінт
Можу ще привести
Саш, хінт - не проблема, його можна погасити відповідною директивою Я не зовсім зрозумію - навіщо це треба 2 Питання 1 хто користуватиметься класом - нащадком - ти чи не ти? 2. метод статичний чи віртуальний?
Якщо взяти саме цей приклад (Add, AddObject), то краще напевно зробити так: переписати метод Add в секції паблік, але додасть параметр (зробити так само, як і в AddObject) (якщо наприклад у стрінг аркуші не повинно виявитися ітем без обжектів)
Вибачте, Warning а не Hint в D7 звучить так:
1 - "Unsafe type PChar" 2 і 3 - "Unsafe type Pointer"
На жаль, я помилився - сховати метод все одно не вдалося. Це можливо тільки за умови винесення предка в інший модуль, як я зрозумів.
Користуватимуся я. Але ж не треба зарікатися-)
Ну сховати неможливо за визначенням, можна розпочати новий ланцюжок успадкування.
Все-таки так і залишилося не зрозумілим, чому саме хочеш приховати, адже цілком достатньо змінити поведінку, тільки треба враховувати й інші методи, наприклад цей метод.викликає Insert який у предка абстрактний, на відміну від Add, також є ще й ряд інших аналогічних методів.
Може, треба подумати над перепроектуванням? Щось десь не те, коли таке знадобилося.
Спадкоємець TStrinList використовується для зберігання списків об'єктів.
У спадкоємці об'єкти можна додавати лише методом AddObject(теж переписаним).
Це робиться для того, щоб список формував строго за певними правилами.
А чому саме спадкоємець від TStringList, а не TList наприклад?
Мені потрібна наявність властивості Strings.
Фактично, в Strings зберігаються ключі, якими виробляється сортування і пошук.
Анатолію, я вже зрозумів, що не вдасться приховати-) Тому піду твоїй пораді - перепишу метод з винятком.
TMasterList=class(TStringList) private // FDB: IDBInterface; //Інтерфейс для роботи з БД FNet: INetInterface; //Інтерфейс роботи з мережею FG: TGuard; //Для роботи з кількома потоками FSortDirect: Boolean; FQuantity: Integer; procedure Add; reintroduce;//Приховуємо метод procedure FreeObject(Index: Integer); procedure CheckKey(aKey: String); //Перевірка на порожній ключ function GetKeys: TStringList; функція GetForumObject(Index: String): TForumObject; procedure SetForumObject(Index: String; const Value: TForumObject); procedure Enter; procedure Leave; // procedure CheckQuantity; protected функція CompareStrings(const S1, S2: string): Integer; override; //Перекритий для методу QuickSort public constructor Create; virtual; Destructor Destroy; override;
function AddObject(aForumObject: TForumObject): Integer; reintroduce;
procedure InsertObject(Index: Integer; aForumObject: TForumObject);повторно вводити; procedure Delete(Індекс: Integer); повторно вводити; перевантаження; procedure Delete(aId: String); повторно вводити; перевантаження; procedure Delete(aObject: TForumObject); повторно вводити; перевантаження; функція IndexOf(const S: рядок): Integer; перевизначити; function Exists(aId: String): Boolean;
функція DeleteFromDB(aId: String): Boolean; віртуальний; функція SyncToDB; віртуальний; функція SyncFromDB; віртуальний; функція SetObjectFromDB; віртуальний; функція AddObjectFromDB; віртуальний; функція WriteObjectToDB; віртуальний; > Ключі властивості: TStringList читання GetKeys; властивість SortDirect: логічне читання FSortDirect запис FSortDirect; властивість ForumObject[Index: String]: TForumObject читання GetForumObject запис SetForumObject; властивість Quantity: Integer read FQuantity write FQuantity; кінець;
Ситуація понятна, сам так частенько роблю, в Strings храню UID на об'єкті, але з написанням свого класу не заморачивался.
Як варіант можна використовувати IndexOfObject, але про сортування тут звичайно річ не йде.
Взагалі звичайно універсальний варіант - наслідувати TStrings, а потрібні методи переносити Copy/Paste.
З TStringList як зручно тим, що не надо вимагати методи у свій модуль;)
Я в такому випадку зробив би по варіанту [10]. Тем більше, якщо планується подальше наращивання спадкоємців
У мові C++ можливо при визначенні класу об'явити тип наслідування. Якщо він, к прикладу, приватні, то публічні методи наступного класу в наступному становляться приватними.
> TGetList=class(TStringList) > приватний > функція Add: Integer; повторно ввести; > кінець;
А якщо не робити TGetList спадкоємцем TStringlist? А зробити типу так:
Тоді доведеться переписати методи длядоступ до SL.
Е-е-е.. так Вам шашечки чи їхати? :-) Якщо потрібно по-чесному саме приховати, то делегування, IMHO, один із найкращих варіантів. Якщо не єдиний.
Див [10]. "Все вже вкрадено до нас" (c)
Ну приховати - це ж побічне завдання, і далеко не найважливіша-) Більш пріоритетна - зручність використання класу. Тому - ну не вдалося приховати, ну і добре-)
Ще раз дякую всім за обговорення.
Не треба використовувати спадкування. Потрібно використовувати композицію. Піст [50] найбільш відповідне рішення.
Не треба плутати програмістів будь-якими reintroduce, що використовуються не за прямим призначенням :)
А чим краще? Вперше вирішив використати успадкування, а тут обламати хочеш такий намір;)
"Якщо батьківський клас у більшості випадків "підмінюватиме" свого нащадка, то використовується успадкування. Якщо ж батьківський клас потрібен лише, щоб клас-нащадок міг використовувати деякі його властивості, то найкращим вибором буде композиція.
Однією фразою: чим більше клас-нащадок схожий на батьківський клас, тим краще використовувати спадкування, а не композицію."
Спадкування має здохнути.
А як, наприклад, змінити порядок сортування в TStringList без наслідування? Та й більшість властивостей батьківського кдасу використовується за призначенням.
Разом із поліморфізмом чи окремо?
> Як, наприклад, змінити порядок сортування в TStringList > без наслідування?
> Та й більшість властивостей батьківського кдасу використовують > за призначенням.
А навіщо тоді такий геморой із прихованням методу Add?
Я ж не буду викликати після кожної операції зі списком CustomSort?
Це, загалом, бувєдине незрозуміле на той момент питання.-)
Спадкування, як воно існує у поширених мовах, занадто каламутне і перевантажене: воно одночасно і опис інтерфейсу, і реалізація інтерфейсу та реюз коду.
А ось народ пише таке:
"Спадкування є корисною концепцією програмування, але не завжди варто вдаватися до неї. Найчастіше з подібними завданнями краще справляються інтерфейси. Цей розділ і розділВипадки використання інтерфейсівдопоможуть вибрати потрібний підхід.
Спадкування краще використовувати у таких випадках.
1.Ієрархія успадкування є відносинами тотожності (is-a), а чи не відносини включення (has-a). 2.Можна повторно використовувати код із базових класів. 3. Необхідно застосувати той же клас і методи до інших типів даних. 4. Ієрархія класу містить досить мало рівнів, і інші розробники навряд чи будуть додавати до неї інші рівні. 5. Необхідно внести докорінні зміни до похідних класів шляхом зміни базового класу. "
З діалогу з директором школи, який отримав у подарунок клас ДВК - Порадьте, як нам отримати від цього максимальну користь. - Цього я не можу. Але можу порадити, як отримати від цього мінімальну шкоду.
Подивіться краще сюди: http://zonnon.ethz.ch/papers/Zonnon_Language_Report_v02r02_2_y041101.pdf
Подивився. Але не можу сказати, наскільки приживеться.
Ця, не вбивайте гілку, плиз. У мене у світлі цього обговорення також питання. Просто зараз ніколи. ;0)
Я солідарний з [10] та [50]. Я зробив би так. Якщо, звичайно, Олександру не потрібно передавати свій список кудись, де очікується інтерфейс базового класу TStringList.
А взагалі, все залежить від завдання, яке стоїть перед Олександром.У випадках, я нічого поганого в раді Анатолія (порушувати виняток) не бачу.
Якщо не помиляюся, то в плюсах можна ховати методи/конструктори/деструктори.
Це якщо треба зробити імітацію абстрактного методу або просто запобігти неправильному використанню. Але все визначається завданням, я ж подробиць не знаю.
Тут висловлювалося негативне ставлення до наслідування. Не бачу нічого в ньому поганого. ІМХО в дизайні має бути все збалансовано.
Як баланс можу навести приклад бібліотеку "свінг" в java. Вважаю, що реалізований у них підхід з використання поліформізму і спадкування дуже лаконічний.