Анализ полиморфизмов в Delphi
1 Что является полиморфизмом? 2
1.1 Концепция 2
1.2 Значение полиморфизма 2
1.3 Как реализовать полиморфизм в Delphi? 2
1.3.1 Наследование 2
1.3.2 Виртуальные методы, динамические методы и абстрактные методы, VMT/DMT, статическое связывание и динамическое связывание 2
1.3.3 Перегрузка и полиморфизм 2
1.4 Обсуждение полиморфных видов 2
1.4.1 двухуровневый полиморфизм 2
1.4.2 Небезопасный полиморфизм 2
2 Применение полиморфизма в VCL2
2.1 Метод строительства и разрушения 2
2.2 TStrings2
2.3 Другие (пожалуйста, добавьте душу) 2
Абстрактный полиморфизм является душой объектно-ориентированной.
Полиморфизм ключевого слова , наследование, объектно-ориентированный, VCL, виртуальный метод, переопределение
вопрос
Полиморфизм является душой объектно-ориентированной, а понимание полиморфизма является одним из ключей к освоению объектно-ориентированной технологии. Но что такое полиморфизм? В чем смысл полиморфизма? Как достичь полиморфизма? Я могу понять концепцию полиморфизма, но я не знаю, как его использовать и когда его использовать? Пожалуйста, прочтите эту статью подробно.
Экспертный анализ
Мир (объект, то есть объект), постоянно меняется; Хорошо в компьютерном языке. Вся индустрия программного обеспечения была заземляющей. Появились ориентированные инструменты разработки, такие как VC, Delphi и BCB. Ориентированный дизайн (OOD), объектно-ориентированный анализ (OOA) и объектно-ориентированная база данных (OODB)), объектно-ориентированная технология почти проникла в область программного обеспечения, а образ мышления программистов также претерпел фундаментальные изменения! В глазах некоторых теоретиков очищения ОО все является объектом! Хотя я не совсем согласен с этой точкой зрения. Но я думаю, что этот метод больше всего соответствует привычкам мышления людей Мозг с тех пор я был освобожден! Это революция!
Основным содержанием объектно-ориентированного является объект, инкапсуляция, наследование, полиморфизм и полиморфизм сообщений. Мастер-полиморфизм, вы не будете овладеть объектно-ориентированной технологией.
1 Что является полиморфизмом?
1.1 Концепция
Есть много разных мнений о концепции полиморфизма, и ниже приведены несколько репрезентативных утверждений:
«Эта способность манипулировать более чем одним типом с указателем или ссылкой на базовый класс, говорящий о полиморфизме» (C ++ Primer, Page 838). То есть способность управлять объектами нескольких классов (базовый класс и его производные классы), используя указатели/ссылки на базовые классы, называется полиморфизмом. Это рассматривается с точки зрения реализации языка.
«Полиморфизм обеспечивает еще одно измерение отделения границы раздела от реализации, чтобы отделить то, что от того, как» («Подумайте в Java» 3 -е издание), то есть полиморфизм обеспечивает другой вид раздела и реализацию (то есть «что делать» и и реализация (то есть «что делать» и и реализация «Как сделать масштаб« отдельно ». Это рассматривается с точки зрения дизайна.
«Способность использовать одно и то же выражение для обозначения различных операций называется полиморфизмом» (объектно-ориентированные методы Принципы и практика 3-е издание, стр. 16). Проще говоря, полиморфизм - это «одно и то же выражение, разные операции», или можно сказать, что «та же команда, разные операции». Это с точки зрения объектно-ориентированной семантики.
Три утверждения объясняют сущность полиморфизма с разных точек зрения. Третье утверждение особенно точное.
Позвольте мне сначала объяснить значение этого предложения:
То же выражение - функциональный вызов
Различные операции - существуют разные операции в соответствии с различными объектами.
For example, in a company, there are various employees with different responsibilities (programmers, salesmen, document managers, etc.) who do different things when they "go to work" (can also be regarded as a kind of business logic) , We Аннотация их соответствующая работа как «работать», а отношения следующие:
персонал
/ |
Менеджер документов продавца программиста
Как только рабочее время наступает каждый день, это эквивалентно выдаче такого команды:
«Сотрудники. Начните работать» (то же выражение)
After each employee receives this command (the same command), he "starts to work", but what they do is their respective work, the programmer starts "Coding", the salesperson starts "contact business", and the cultural manager Let's start “ Организация документов ». То есть «одно и то же выражение (вызов функции), разные операции (выполнять в соответствии с различными объектами в течение периода выполнения)».
С точки зрения языковой реализации полиморфизма полиморфизм достигается путем вызова его виртуального метода с помощью указателей базового класса или ссылок на объекты, указывающие на полученные классы. Ниже приводится реализация объекта Pascal Language
Temployee = Class // Аннотация сотрудников в абстрактный класс
публичный
Процедура Startworking; Virtual; Аннотация;
{Абстрактные функции (то есть чистые виртуальные функции в C ++), ничего не делайте, фактическое значение состоит в том, чтобы сначала зарезервировать интерфейс. Перегрузка реализует его в своем полученном классе. }
конец;
Tprogramer = class (Temployee) // Программист
публичный
Процедура стартовать;
конец;
Tbusinessman = class (Temployee) // Продавец
публичный
Процедура стартовать;
конец;
Tdocmanager = class (Temployee) // Текстовый диспетчер
публичный
Процедура стартовать;
конец;
Процедура tprogramer.startworking;
Начинать
ShowMessage ('кодирование');
конец;
{Tbusinessman}
Процедура tbusinessman.tartworking;
Начинать
ShowMessage («связывание бизнеса»);
конец;
{Tdocmanager}
Процедура tdocmanager.startworking;
Начинать
ShowMessage («Управление документом»);
конец;
Процедура tform1.button1click (отправитель: tobject);
констант
enum = 3;
вар
Сотрудник: массив Temrokeate;
я: целое число;
Начинать
setLength (сотрудник, enum);
Сотрудник [0]: = tprogramer.create;
// обратитесь к сотруднику базового класса [0], чтобы указать на только что созданный объект TPROGRAMER
Сотрудник [1]: = tbusinessman.create;
// См. Сотруднику базового класса [1], чтобы указать на объект Tbusinessman, который вы только что создали
Сотрудник [2]: = tdocmanager.create;
// обратитесь к сотруднику базового класса [2], чтобы указать на только что созданный объект Tdocmanager
для i: = 0 до длины (сотрудник) -1 do
Сотрудник [i].
{С точки зрения полиморфизма реализации языка полиморфизм реализуется, вызывая его виртуальный метод с помощью указателя базового класса или эталонного объекта, указывающего на производные классы. Сотрудник [] относится к массиву для объекта базового класса, и его участники указывают на различные объекты полученных классов соответственно.
конец;
Попробуйте
Вы можете ввести некоторые из приведенных выше кода (или демонстрационных программ), компилировать и запустить, и нажать кнопку, чтобы увидеть магический эффект полиморфизма.
1.2 Значение полиморфизма
Значение инкапсуляции и наследства заключается в том, что они реализуют повторное использование кода, в то время как значение полиморфизма заключается в том, что он реализует повторное использование интерфейса (то же выражение). Способность.
Например, чтобы лучше управлять, программисты делятся на программистов C ++ и Delphi программистов. …
персонал
/ |
Менеджер документов продавца программиста
/ / - - взаимосвязь
Программист C ++ Delphi Progrommer
После того, как программист добавил два полученных класса TCPPProgramer и Tdelphiprogramer, метод вызова все еще не изменился, и он все еще был «сотрудниками. Начните работать», который был описан с Object Pascal:
…
setLength (сотрудник, enum+2);
Сотрудник [enum]: = tcppprogramer.create;
// Создать объект TCPPProgramer и указать на него на справочный сотрудник базового класса [enum]
Сотрудник [enum+1]: = tdelphiprogramer.create;
…
{Сектора.
для i: = 0 до длины (сотрудник) -1 do
Сотрудник [i].
…
1.3 Как реализовать полиморфизм в Delphi?
Необходимыми условиями для достижения полиморфизма являются наследование, виртуальные методы, динамическое связывание (или связывание с задержкой).
1.3.1 Наследование
Наследование относится к «ако (своего рода, а)« взаимосвязь между классом, таким как программист », является« сотрудником, указывающим на отношения наследования. В Delphi поддерживается только единое наследство (не учитывает множественное наследство, реализованное интерфейсами). Полученные объекты класса (или наоборот).
намекать
В UML:
AKO: своего рода средние отношения наследования
APO: часть представляет собой комбинированную связь
ISA: ISA представляет отношения между объектом и классом, к которому он принадлежит.
1.3.2 Виртуальные методы, динамические методы и абстрактные методы, VMT/DMT, статическое связывание и динамическое связывание
Для всех методов в объекте нет следа. Его указатель метода (адрес записи) хранится в классе, в то время как фактический код хранится в сегменте кода. Для статических методов (не виртуальных методов) компилятор непосредственно определяет адрес входа метода объекта на основе ссылочного типа объекта во время компиляции, который называется статическим связыванием; Компилятор не может определить фактический класс, к которому он принадлежит, поэтому адрес входа метода может быть определен только через адрес записи таблицы VMT (то есть первые четыре байта объекта) во время выполнения. задержка).
Виртуальный метод
Виртуальный метод представляет собой метод, который может быть переоборудован. В дополнение к хранению собственного указателя виртуального метода, класс также хранит указатель виртуального метода всех базовых классов.
Метод объявления:
Имя метода процедуры;
Это эквивалентно сообщению компилятору Delphi:
Этот метод может быть перегружен в полученном классе, а виртуальный метод будет все еще после перегрузки.
Не определяйте адрес входа метода в течение периода компиляции. Во время выполнения адрес входа метода определяется посредством динамического связывания.
Предоставьте реализацию по умолчанию в базовом классе.
Динамический метод
动态方法和虚方法本质上是一样的,与虚方法不同的是,动态方法在类中只存储自身动态方法指针,因此虚拟方法比动态方法用的内存要多,但它执行得比较快。 Но это полностью прозрачно для пользователей.
Метод объявления:
Имя процедуры; Dynamic;
Абстрактные методы
Специальный виртуальный метод, который не должен обеспечивать реализацию по умолчанию в базовом классе, просто используется для вызова интерфейса, что эквивалентно чистой виртуальной функции в C ++. Классы, содержащие абстрактные методы, называются абстрактными классами.
Метод объявления:
Имя процедуры; виртуально; абстрактный;
VMT/DMT
В Delphi таблица виртуальных методов (VMT) на самом деле не физически. Виртуальные методы его базового класса. «Адрес в записи VMT», хранящийся в первых четырех байтах объекта, на самом деле является адресом класса, которому он принадлежит (см. Демо -программу). С фактическим классом можно найти адрес виртуального метода.
Obj (имя объекта) класс, которому принадлежит фактический объект
Адрес записи VMT
Данные члены
Адрес ввода VMT таблицы виртуальных методов класса
Информация о шаблоне членов данных
Статические методы и т. Д.
Виртуальный метод (VMT)
Динамический метод (DMT)
Рисунок 3 Соотношение между именами объектов, объектами и классами
DMT похож на VMT и также является логической концепцией. не так быстро, как виртуальных методов.
Приводите приведенный выше пример, чтобы объяснить:
Сотрудник [i].
Сотрудник [i] является ссылкой на объект базового класса Templeyee. Таким образом, фактический объект не может быть известен во время компиляции, поэтому адрес метода не может быть определен. В течение периода пробега, конечно, я знаю «Истинное лицо Лушана» объекта. Функция, которая должна быть названа, то есть полиморфизм реализован.
1.3.3 Перегрузка и полиморфизм
Многие пользователи сети считают, что перегрузка функций также является своего рода полиморфизмом, но это не так. Для «разных операций» перегрузка не может обеспечить тот же метод вызова. Предпосылка реализации полиморфизма - это то же самое выражение! Например, сотрудник [i]. Перегрузка-это просто языковой механизм, и в C также есть перегрузка, но C не имеет полиморфизма, а C не является объектно-ориентированным языком программирования. Если функция перегрузки также не является виртуальным методом, компилятор может определить адрес записи функции на основе типа параметра или статического привязки! Цитируйте отца C ++: «Не будь глупым. Если это не динамическое связывание, это не полиморфизм».
1.4 Обсуждение полиморфных видов
1.4.1 двухуровневый полиморфизм
对象级:用基类指针/引用指向其派生类对象,调用虚方法(或动态方法、抽象方法),这是用的最多一种。
Уровень класса: используйте ссылки класса (ссылки на классы, а не на объекты), чтобы указывать на полученные классы, вызовать методы виртуального класса (или динамические методы класса, абстрактные методы класса) и обычно используются в полиморфизмах, создаваемых объектами (потому что конструктор - это Вид «для особых» методов типа, пожалуйста, обратитесь к моей другой работе «Анализ структуры и разрушения в Delphi», раздел 2.1).
намекать
Ссылка на класс является эталонной переменной самого класса, а не классом, ни ссылкой на объект. Точно так же, как имя объекта представляет ссылку на объект, имя класса представляет собой ссылку класса, потому что в Delphi класс также обрабатывается как объект. Тип ссылки класса - это тип ссылки класса, а метод объявления типа ссылки класса:
Имя типа ссылки класса = класс имени класса
Мы можем увидеть много справочных объявлений класса в исходном коде VCL, таких как:
Tclass = класс Tobject;
TcomponentClass = класс TComponent;
Tcontrolclass = класс TControl;
Уведомление
В методе класса самостоятельно в методе является ссылка на класс, а не ссылка на объект.
1.4.2 Небезопасный полиморфизм
Полиморфизм также может быть реализован с использованием полученных указателей класса/ссылок на объекты базового класса!
Процедура tform1.btnbadpolyclick (отправитель: tobject);
вар
CPPProgramer: TCPPProgramer; // Определить ссылку на программист CPP, ссылку на полученный класс!
Начинать
{*****************************заявление******************* ************************
Полиморфизм, реализованный с полученными указателями класса/ссылки на объекты базового класса. Это патологический полиморфизм!
Этот полиморфный метод похож на очень маленькую вещь (объект базового класса), который покрыт мощным
Появление продукта (полученные ссылки на классы) приводит к множеству потенциальных факторов отсутствия безопасности (таких как исключения доступа), поэтому
Почти без значения. «Файл» Пример направлен на иллюстрацию природы полиморфизма в Delphi, природа полиморфизма: используйте указатель/ссылка на базовый класс) для работы, согласно фактическому объекту во время выполнения, для выполнения различной операции Методы или более яркое утверждение: сам объект решает свой собственный метод работы. объект. Это позволяет разделить интерфейсы и реализации, что делает возможным повторное использование интерфейса.
********************************************* ******* *******************************
cppprogramer: = tcppprogramer (tprogramer.create);
{Чтобы достичь этого патологического полиморфизма, ссылка на объект приводит к типу TCPPProgramer,
Таким образом, ускользает от проверки компилятора}
cppprogramer.startworking;
{Tprogramer.Startworking называется вместо tcppprogramer.startworking
Это полиморфизм, реализованный с полученными указателями класса/ссылки на объект базового класса. }
cppprogramer.free;
cppprogramer: = tcppprogramer (tdocmanager.create);
cppprogramer.startworking;
{Вызов tdocmanager.Startworking,
Это полиморфизм, реализованный с полученными указателями класса/ссылки на объект базового класса. Этот метод чрезвычайно небезопасен.
И нет необходимости}
cppprogramer.free;
конец;
Попробуйте
Чтобы получить такого рода перцептивное понимание полиморфизма, рекомендуется попробовать его ? При каких обстоятельствах произойдет исключение доступа? (См. Демо -программу)
2 применения полиморфизма в VCL
2.1 Методы строительства и разрушения
Полиморфизм метода строительства
Поскольку конструктор может рассматриваться как «специальный» метод класса, все полученные классы после того, как Tomponent переопределяются как виртуальные методы класса, поэтому для реализации полиморфизма конструктора вы должны использовать ссылки на класс. В каждом файле проекта есть код, похожий на следующее:
Application.createform (tform1, form1);
Определение его метода:
Процедура tapplication.createform (instanceClass: tcomponentClass; var ссылка);
var // instanceclass является ссылкой на класс.
Экземпляр: tcomponent;
Начинать
Экземпляр: = tcomponent (instanceclass.newinstance);
{Newinstance Declaration: Функция класса NewInstance: Tobject; InstanceClass-это ссылка на класс, которая реализует полиморфизм на уровне класса, тем самым реализуя повторное использование интерфейса для создания компонентов}
Tcomponent (ссылка): = экземпляр;
пытаться
Exance.create (self); // вызвать конструктор, чтобы инициализировать его
кроме
Tcomponent (ссылка): = nil; // Устранение «дикого» указателя! хороший
поднимать;
конец;
{Если созданное окно и еще нет основной формы, установите только что созданную форму в качестве основной формы}
if (fmainform = nil) и (экземпляр tform), затем
Начинать
Tform (экземпляр) .handleneeded;
Fmainform: = tform (encement); // Установить основную форму
{Фактически, установление основной формы в параметрах проекта (Project-> Options) на самом деле является соответствующим оператором формы в файле проекта перед всеми операторами создания форм. }
конец;
конец;
2) Для полиморфизма метода деструкции, пожалуйста, см. «Анализ структуры и разрушения в Delphi», раздел 3.3
2.2 TStrings
字符串数组处理在Delphi的控件中十分常见,通常是一些Items属性,我们用起来也特别地方便(因为都是一样的使用接口),这得益于Delphi中字符串数组的架构的设计。 Это успешный дизайн.
Поскольку многие элементы управления используют строковые массивы, такие как ComboBox, TStringGrid и т. Д., Но строковые массивы в каждом управлении разные, Delphi абстрагирует строковые массивы, поэтому появляется много связанных классов. Базовый класс TStrings предоставляет только интерфейс для различных вызовов, и конкретная реализация может быть полностью реализована из его полученных классов.
Давайте посмотрим на определение общих методов класса базового класса TStrings (см. Классы единицы строки 442):
Tstrings = class (tpersistent)
защищен
...
Функция GET (Index: Integer): String;
процедура PUT (Index: Integer; Const S: String);
Функция GetCount: целое число;
…
публичный
Функция добавить (const s: string): целое число;
{Добавить строку s в конец списка строк}
процедура добавления (строки: tstrings);
{Добавить строки в конец списка строк}
Процедура вставка (Индекс: Integer; Const S: String);
{Abstract Method, вставьте новую строку S в позицию индекса}
процедура ясна;
{Очистить все строки}
Процедура удалить (индекс: целое число);
{Удалить строку в определенном месте}
Функция Indexof (const S: String): целое число;
{Получить позицию S в списке строк}
Функция indexofname (const name: string): integer;
{Возвращает позицию первой строки с значением Form = с указанной частью имени}
Функциональный индекс (aobject: tobject): целое число;
{Получить позицию объекта с объектом с именем aObject: в списке строк}
Процедура загрузка FromFile (const fileName: String);
{Заполняет список строками текста в указанном файле}
Процедура загрузка от потока (поток: tstream);
{Заполняет список строками текста, считываемых из потока}
процедура SavetoStream (поток: tstream);
{Записывает значение свойства текста в объект потока}
Струкные строки [Индекс: Integer]: строка Читать
{Ссылка на строки в списке по их позициям}
Значения свойства [const name: string]: string read getValue write setValue;
{Представляет значение значения строки, связанную с данным именем, на строках с формой name = value.}
…
конец;
Из определения TStrings можно увидеть, что большинство его защищенных и публичных методов являются виртуальными методами или абстрактными методами. (Пожалуйста, добавьте немного, tstringlist-> tstringgridstring)
2.3 Другие (пожалуйста, добавьте душу)
Если вы еще не понимаете полиморфизм, пожалуйста, помните сущность полиморфизма:
«То же выражение, разные операции» (это так просто)
С точки зрения реализации языка ООП полиморфизм должен использовать указатель/ссылку на базовый класс для работы (полученный класс) объектов и выполнять различные методы работы в соответствии с фактическим объектом в течение периода прогона; Более яркое утверждение: объект решает свой собственный метод работы. сам Это позволяет разделить интерфейсы и реализации, что делает возможным повторное использование интерфейса.
На самом деле, полиморфизм прост! Итак, на что вы должны обратить внимание при использовании полиморфизма? Вот мои два предложения:
Проанализируйте бизнес -логику, затем абстрактно связаны с «объектами», а затем инкапсулируйте бизнес -логику, используя методы объектов. Объявите некоторые операции с полиморфизмом как виртуальные методы в базовом классе и объявить их виртуальными абстрактными методами для тех, кто не требуется для реализации в базовом классе, а затем перегружайте их в своих полученных классах. /указатели базового класса при использовании, что, естественно, реализует полиморфизм в реальном мире. Помните, чтобы не достигать полиморфизма ради полиморфизма.
Поскольку существует естественная связь между базовыми классами и полученными классами, модификация базовых классов приведет к «достижению всего тела», что будет очень хлопотно! Поэтому мы должны попытаться ослабить функциональную реализацию базового класса, разработать его как «абстрактный класс», если это необходимо, и обеспечить стабильный интерфейс.
Связанные вопросы
Обсудите полиморфизм Delphi: http://www.delphhibbs.com/delphhibbs/dispq.asp?lid=1753965
О полиморфизме: http://www.delphhibbs.com/delphhibbs/dispq.asp?lid=1854895
Что такое полиморфизм? Каковы использование в ежедневном программировании? http://www.delphibbs.com/delphibbs/dispq.asp?lid=960465
В чем разница между перегрузкой и переопределением? http://www.delphibs.com/delphibs/dispq.asp?lid=296739
Выпуск того, что указатель полученного класса указывает на объект базового класса http://www.delphibs.com/delphibs/dispq.asp?lid=2104106
(Последний вопрос был упомянут на Delphibbs, когда я глубоко изучал полиморфизм, что вызвало жаркую дискуссию. Я предлагаю вам взглянуть)