Блог gunsmoker-а (переклади) віртуальні методи і inherited

Віртуальні методи і inherited

Delphi має незвично багату мовну підтримку поліморфного поведінки. Найпростіша і базова, яку більшість програмістів асоціюють з поліморфізмом, - це віртуальні методи.

Віртуальний метод оголошується в своєму базовому класі з використанням директиви virtual. Базовий клас може мати реалізацію за замовчуванням для віртуального методу, а може і не мати. Якщо реалізації за замовчуванням немає, то ви помічаєте метод як абстрактний (директива abstract), змушуючи спадкоємців класу створювати свою реалізацію методу в обов'язковому порядку. Все це - базові речі, які знають все Delphi програмісти. Залежно від реалізації (і документації!) Базового класу, клас-спадкоємець може вирішити викликати успадкований метод на самому початку, перед виконанням своїх дій, або в середині (досить рідко), або після своїх дій, в кінці, або ж не викликати зовсім . Існує два способи виклику успадкованого варіанту методу, з тонкими відмінностями: Цей код безумовно викличе успадкований метод Draw базового класу. Якщо метод в базовому класі - абстрактний, то цей виклик завершитися невдачею, збуджуючи виняток EAbstractError під час виконання (або Run-Time помилку 210, якщо ви не використовуєте виключення).

Альтернативний синтаксис виклику - просто написати inherited ;. наприклад: Цей код буде працювати ідентично попередньому для випадків, коли клас містить не абстрактний метод. Цей код також автоматично створюється засобом автодоповнення коду, коли ви реалізуєте заміщення методу (override). Крім того, він же використовується IDE, при вставці обробників подій форм з візуальним спадкуванням.

Якщо ж метод базового класу є абстрактним, або ж базовий клас взагалі не містить методу (для не віртуально методів), то виклик inherited стає noop (No-Operation - порожнім оператором). Компілятор не генерує для нього коду (і тому ви не можете поставити на нього точку зупину). Цей механізм є частиною відмінною версійність стійкості мови Delphi.

Один підводний камінь з синтаксисом inherited; - він не підтримується для функцій. Для функцій вам потрібно використовувати явний синтаксис із зазначенням імені методу і його аргументів. Наприклад: Це може виглядати як надмірне обмеження дизайну мови Delphi, але я думаю, що це не випадково. Сенс цього, ймовірно, в тому, що якщо TMyClass.MethodC є абстрактним (або буде зроблений абстрактним в майбутньому), то присвоювання результату виклику в Result в класі-нащадку буде видалено, що призведе до несподіваного невизначеному значенню. Це, звичайно ж, призведе до прихованих Багам в коді.

Однак, я думаю, що тут є невеличка прогалина в синтаксисі успадкованого виклику. Багато в чому процедура, яка приймає out параметри (а в деяких випадках і var параметри), поводиться як функція, яка повертає результат. Так, на мій погляд, синтаксис inherited; повинен бути заборонений при виклику методів з out (і, можливо, var) параметрами. Зараз це не так. Цей код означає, що якщо метод батьківського класу є абстрактним (або просто відсутня в разі не віртуального методу), то значення вихідного параметра буде невизначеним. На мій погляд, компілятор повинен забороняти такі виклики inherited ;. вимагаючи явного синтаксису inherited MethodB (A); Але кота вже випустили з мішка і вже занадто пізно щось міняти - блокування подібних викликів з помилкою компіляції виразно поламає купу коду, так що, ймовірно, це тягне максимум на попередження (warning).

Взагалі не знав, як використовувати директиву virtual * oops *

Дякую за зрозумілу статтю. )

Один підводний камінь з синтаксисом inherited; - він не підтримується для функцій. Для функцій вам потрібно використовувати явний синтаксис із зазначенням імені методу і його аргументів
Чесно - вперше про це чую. Користувався таким синтаксисом і в Д7, і зараз в ХЕ - ніяких обмежень. І навіть ваш приклад відмінно компілюється і працює як очікується

Наскільки я розумію, це копія старої статті з The Delphi Magazine (можу помилятися, звичайно). Але, в будь-якому випадку, оригінал був написаний, мабуть, досить давно. Якщо не плутаю, то це поведінка була до Delphi 4 включно, а в Delphi 5 його прибрали.

Текст вирішив залишити для ознайомлення з проблемою абстрактного методу-функції. Хоча тепер розумію, що треба було додати примітку.

Один підводний камінь з синтаксисом inherited; - він не підтримується для функцій.
У Delphi XE саме так. Доводиться писати влоб:
Result: = inherited;
Інакше значення з базового класу не передається.

Можна використовувати деякі HTML-теги, наприклад:

Будь ласка, по можливості використовуйте "Ім'я / URL" замість "Анонімний". URL можна просто не вказувати.

Ваше повідомлення може бути позначено як спам спам-фільтром - не хвилюйтеся, воно з'явиться після перевірки адміністратором.

Пошук по блогу