Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Begin.






ENDDraw;

PROCEDURE (f: Figure) Move (dx, dy: INTEGER); BEGIN... END Move;

Draw и Move связаны с типом Figure, из чего следует, что обе они могут быть применимы к объектам типа Figure. Эти процедуры рассматриваются как локальные по отношению к FigureDesc и к ним можно обращаться как к обычным полям записи, например:

f.Move(10, 10), если f— это переменная типа Figure.

Любая процедура, связанная с типом T, неявно также связана и со всеми расширениями типа T. Она может быть переопределена (перегружена) процедурой с тем же самым именем и точно таким же списком формальных параметров, как и та, что явным образом связана с расширением T. Взгляните на пример:

TYPE Circle = POINTER TO CircleDesc; CircleDesc = RECORD (FigureDesc) radius: INTEGER END; PROCEDURE (c: Circle) Move (dx, dy: INTEGER); BEGIN... END Move;

Тип Circle является расширением типа Figure. Процедура Move явным образом связана с Circle и переопределяет процедуру Move, которая была «унаследована» от Figure. Пусть «f» — это переменная типа Figure, а «c» — переменная типа Circle, тогда присваивание f: = c меняет у переменной «f» ее динамический тип (ее тип) с Figure на Circle. В вызове

f.Move(10, 10)

переменная «f» выполняет две функции: во-первых, она передается в качестве параметра-получателя процедуре Move, а во-вторых, ее динамический тип определяет то, какой вариант Move в действительности вызывается. Так как после присваивания f: = c динамический тип переменной «f» уже Circle, то вызывается процедура Move, которая связана с типом Circle, а не та, что связана с типом Figure. Этот механизм называется динамическим связыванием (dynamic binding), поскольку динамический тип получателя используется для связывания имени процедуры с реальной процедурой.

Внутри переопределяющей (redefining) процедуры переопределяемая (redefined) процедура может вызываться с использованием значка ^, например: f.Move^(dx, dy).

Аргументация. Мы отказались от введения концепции класса, а вместо этого заменили его на хорошо известную концепцию записи. Таким образом, класс — это просто тип запись со связанными с ним процедурами. Мы также отказались от дублирования в самой записи заголовков типизированных процедур, как это сделано в других языках типа C++ и Object Pascal. Это позволяет сохранить записи короткими и избежать избыточности описаний. Ведь изменение в заголовке тогда повлекло бы за собой корректировку в двух разных местах программы, к тому же компилятору пришлось бы еще и проверять идентичность обоих заголовков. Если программист захочет увидеть конкретную запись со всеми связанными с ней процедурами, то он может для получения информации на экране или на листе бумаги воспользоваться специальным инструментом, который называется навигатор модулей (browser).

Процедуры, привязанные к типу, могут быть объявлены в произвольном порядке. Их можно даже перемежать процедурами, привязанными к другому типу. В языке Object Oberon, где все методы должны быть объявлены внутри соответствующего объявления класса, обнаружилось, что косвенная рекурсия между методами различных классов может поставить в затруднительное положение предварительные описания целых классов.

В языках типа Object Pascal и C++ переменные экземпляра (instance variable) для объекта-получателя «self» могут быть доступны как с квалификацией, так и без нее (например, можно написать и «x», и «self.x»). В этих языках подчас трудно определить, что перед вами — обычная переменная или же переменная экземпляра. Бывает еще сложнее, когда имя обозначает переменную экземпляра, которая унаследована от базового класса. По этой причине мы решили, что переменные экземпляра в языке Oberon-2 должны всегда квалифицироваться. Таким образом, удается избежать выбора между двумя семантически эквивалентными конструкциями, что на наш взгляд нежелательно для языков программирования.

В языке Oberon-2 получатель представляет собой явный параметр, а потому программист может выбирать для него характерное имя, которое обычно выглядит куда более выразительнее, чем предопределенное имя «self», что используется в других объектно-ориентированных языках. Явное объявление получателя проясняет ту картину, что объект, к которому применяется данная операция, передается этой операции в качестве параметра. Это обычно нельзя выразить в других объектно-ориентированных языках. К тому же такой подход четко следует духу Oberon’а — избегать любых скрытых механизмов.

В языке Object Oberon методы имеют в точности такой же синтаксис, как и обычные процедуры. В больших классах, где заголовка класса не видно рядом с заголовком метода, невозможно понять, является ли данная процедура обычной процедурой или же перед нами метод. В этом случае трудно также понять, к какому классу данный метод относится. В языке Oberon-2 тип параметра-получателя типизированной процедуры обозначает тип, с которым процедура связана, поэтому никаких сомнений не возникает.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.