![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Три механизма, обеспечивающие полиморфизм
Под полиморфизмом в ООП понимают способность одного и того же программного текста x.M выполняться по-разному, в зависимости от того, с каким объектом связана сущность x. Полиморфизм гарантирует, что вызываемый метод M будет принадлежать классу объекта, связанному с сущностью x. В основе полиморфизма, характерного для семейства классов, лежат три механизма:
В совокупности это и называется полиморфизмом семейства классов. Целевую сущность часто называют полиморфной сущностью, вызываемый метод - полиморфным методом, сам вызов - полиморфным вызовом. Вернемся к нашему примеру с классами Found, Derived, ChildDerived. Напомню, в родительском классе определен виртуальный метод VirtMethod и переопределен виртуальный метод ToString родительского класса object. Потомок класса Found - класс Derived переопределяет эти методы: public override void VirtMethod(){ Console.WriteLine(" Сын: " + this.ToString()); }public override string ToString(){ return(String.Format(" поля: name = {0}, credit = {1}, debet ={2}", name, credit, debet)); }Потомок класса Derived - класс ChildDerived не создает новых полей. Поэтому он использует во многом методы родителя. Его конструктор состоит из вызова конструктора родителя: public ChildDerived(string name, int cred, int deb): base (name, cred, deb) {}Нет и переопределения метода Tostring, поскольку используется реализация родителя. А вот метод VirtMethod переопределяется: В классе Found определены два невиртуальных метода NonVirtmethod и Work, наследуемые потомками Derived и ChildDerived без всяких переопределений. Вы ошибаетесь, если думаете, что работа этих методов полностью определяется базовым классом Found. Полиморфизм делает их работу куда более интересной. Давайте рассмотрим в деталях работу метода Work: public void Work(){ VirtMethod(); NonVirtMethod(); Analysis(); }При компиляции метода Work будет обнаружено, что вызываемый метод VirtMethod является виртуальным, поэтому для него будет применяться динамическое связывание. Это означает, что вопрос о вызове метода откладывается до момента, когда метод Work будет вызван объектом, связанным с x. Объект может принадлежать как классу Found, так и классам Derived и ChildDerived, в зависимости от класса объекта и будет вызван метод этого класса. Для не виртуальных методов NonVirtMethod и Analysis будет применено статическое связывание, так что Work всегда будет вызывать методы, принадлежащие классу Found. Однако и здесь не все просто. Метод NonVirtMethod public void NonVirtMethod(){ Console.WriteLine (" Мать: " + this.ToString()); }в процессе своей работы вызывает виртуальный метод ToString. Опять-таки, для метода ToString будет применяться динамическое связывание, и в момент выполнения будет вызываться метод класса объекта. Что же касается метода Analysis, определенного в каждом классе, то всегда в процессе работы Work будет вызываться только родительский метод анализа из-за стратегии статического связывания. Хочу обратить внимание на важный принципиальный момент. Вполне понятно, когда потомки вызывают методы родительского класса. Потомкам все известно о своих предках. Но благодаря полиморфизму методы родительского класса, в свою очередь, могут вызывать методы своих потомков, которых они совсем не знают и которые обычно и не написаны в момент создания родительского класса. Достигается это за счет того, что между родителями и потомками заключается жесткий контракт. Потомок, переопределяющий виртуальный метод, сохраняет сигнатуру метода, сохраняет атрибуты доступа, изменяя реализацию метода, но не форму его вызова. Класс Found, создающий метод Work, говорит примерно следующее: " Я предоставляю этот метод своим потомкам. Потомок, вызвавший этот метод, должен иметь VirtMethod, выполняющий специфическую для потомка часть работы; конечно, потомок может воспользоваться и моей реализацией, но допустима и его собственная реализация. Затем часть работы выполняю я сам, но выдача информации об объекте определяется самим объектом. Заключительную часть работы, связанную с анализом, я потомкам не доверяю и делаю ее сам".
|