OberonCore
https://forum.oberoncore.ru/

Перегрузка методов
https://forum.oberoncore.ru/viewtopic.php?f=1&t=5374
Страница 1 из 1

Автор:  Kemet [ Суббота, 28 Март, 2015 19:29 ]
Заголовок сообщения:  Перегрузка методов

Зачем в КП ввели перегрузку методов? Какие проблемы решаются таким образом?

Автор:  Илья Ермаков [ Суббота, 28 Март, 2015 20:05 ]
Заголовок сообщения:  Re: Перегрузка методов

Вы имеете в виду, когда B extend A, у А есть неабстрактный Do, и я в B могу его переопределить (ну и делать супервызов A.Do^)?

Автор:  Kemet [ Суббота, 28 Март, 2015 21:21 ]
Заголовок сообщения:  Re: Перегрузка методов

Я имею ввиду модификатор NEW.
В Оберонах( и в Модуле 3, кстати ) все методы - виртуальные, поэтому в наследнике эти методы переопределяются, т.е. в виртуальной таблице методов наследника перезаписывается тот же самый слот, такое проведение называется OVERRIDE.
Модификатор же NEW позволяет создать в наследнике метод с таким же именем, но с другой сигнатурой, для этого в VMT создается новый слот. Это, по сути, и есть механизм перегрузки методов - OVERLOAD

Автор:  Пётр Кушнир [ Суббота, 28 Март, 2015 23:21 ]
Заголовок сообщения:  Re: Перегрузка методов

NEW обозначает только то, что метод появился в этом рекорде, а не в предке.
Для заужения результата метода не нужен NEW.
Цитата:
If a method M is bound to a type T0, it is implicitly also bound to any type T1 which is an extension of T0. However, if a method M' (with the same name as M) is declared to be bound to T1, this overrides the binding of M to T1. M' is considered a redefinition of M for T1. The formal parameters of M and M' must match, except if M is a function returning a pointer type. In the latter case, the function result type of M' must be an extension of the function result type of M (covariance) (see App. A). If M and T1 are exported (see Chapter 4) M' must be exported too.

Вот тут компилер не позволил мне поставить NEW для B.New
Код:
MODULE PrivMeth;
   TYPE
      A = EXTENSIBLE RECORD END;
      
      B = RECORD (A) END;
      
      ResultA = POINTER TO ABSTRACT RECORD END;
      
      ResultB = POINTER TO ABSTRACT RECORD(ResultA) END;
      
   PROCEDURE (VAR a: A) New(): ResultA, NEW, EXTENSIBLE;
   BEGIN
   RETURN NIL;
   END New;
   
   PROCEDURE (VAR b: B) New(): ResultB;
   BEGIN
   RETURN NIL;
   END New;
   
END PrivMeth.

Автор:  Kemet [ Суббота, 28 Март, 2015 23:50 ]
Заголовок сообщения:  Re: Перегрузка методов

Пётр, иностранными буквами написано ровно то же самое, что я писал русскими - если мы в производном типе определяем метод с той же самой сигнатурой(тип результата производного метода может быть производным типом от типа результата метода базового типа), то такой механизм называется OVERRIDE.

А NEW позволяет определить в производном типе метод с тем же именем, но с другой сигнатурой, сохраняя метод предка.

В твоём примере сигнатура методов совпадает, поэтому нельзя поставить NEW, т.е. нельзя перегрузить такие методы, потому что появится неоднозначность

Автор:  Пётр Кушнир [ Воскресенье, 29 Март, 2015 02:12 ]
Заголовок сообщения:  Re: Перегрузка методов

Ну так New(n: INTEGER), NEW тоже не прокатывает.

Автор:  Илья Ермаков [ Воскресенье, 29 Март, 2015 05:52 ]
Заголовок сообщения:  Re: Перегрузка методов

Kemet писал(а):
Модификатор же NEW позволяет создать в наследнике метод с таким же именем, но с другой сигнатурой, для этого в VMT создается новый слот. Это, по сути, и есть механизм перегрузки методов - OVERLOAD


Так это в КП не разрешено.
Ну или может сработать для случая, когда метод в базовом классе неэкспортирован (т.е. никакой перезгрузки не будет - нет такого пространства имён, где были бы доступны оба метода).

NEW введён не для перегрузки, а для предотвращения следующей ситуации, от которой нет защиты в других языках:
разработчик компонента B ввёл впервые в своём расщирении метод X,
потом разработчик компонента А (может быть, ничего и не знающий про B) ввел в базовом типе метод с таким же названием.
При совместном использовании этих двух компонентов никто не заметит, "почему поломалось".
А так сразу же будет ошибка при загрузке модулей, а далее разработчик B полезет перекомпилировать - и наткнётся на ошибку компиляции, т.к. у него X, NEW, а в базовом типе уже есть X.

Вообще, в компонентной идеологии не только перезгрузка, но и OVERRIDE не приветствуется. Вообще наследование реализации практически не используется. Только от ABSTRACT.
Где-то в архитектурной справке в ББ OVERRIDE и супервызовы отмечены как устаревающие, помнится.

Сами разработчики ББ для случая, когда есть наследование реализации и нужна модификация поведения метода, используют следующее:
Код:
PROCEDURE (a: A) Do2-, NEW, EMPTY;

PROCEDURE (a: A) Do, NEW;
BEGIN
  что-то делаем свое;
  a.Do2 (* даём поработать типу-расширению *)
END Do;


Тип B(A), если нужно модифицировать Do, реализует Do2.
Do2 вызывать никто не может, кроме модуля, где определён тип-хозяин A (она с -, "только для реализации").

Основное преимущество: командует парадом базовый тип. Он может дать поработать наследнику до своих действий, после или в середине. Без его ведома никто не OVERRID-ит методы.

В общем, EXTENSIBLE для процедур нигде уже не применяется (есть пара мест в ББ, которые самые древние - ещё когда он был на Обероне-2).
EXTENSIBLE для типов тоже крайне редко применяется, типы даже и с некоторыми реализованными методами обычно имеют достаточно много ABSTRACT-методов, т.е. таки получаются ABSTRACT, с частичной реализацией.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/