лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел), страница 14
Описание файла
PDF-файл из архива "лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 14 страницы из PDF
в Аде95 нельзя передавать более одного параметра классового типа:procedure Intersect(X, Y:Figure)...procedure Inter(X, Y:Figure’class) isbeginIntersect(X, Y);end;Мы закончили рассмотрение динамического связывания в рассматриваемых языках.Абстрактные классы.Рассмотрим пример на С++:Class Figure{public: virtual void draw();}Class Line: public Figure{public: virtual void draw();}Class Circle: public Figure{public: virtual void draw();}При сборке будет выдана ошибка о том, что нет реализации для метода draw класса фигуры, даже если егоне разу не вызывали (если объявить невиртуальные метод и не описать его тело, и при этом ни разу невызывать его, то ошибки не будет). Эта ошибка связана с тем, что нужно строить таблицу виртуальныхфункций.
Поэтому нужен механизм абстрактных классов.Нет ОО ЯП, в котором не было бы абстрактных классов.С++:Class Figure {public: virtual void draw() = 0; /* чисто виртуальный (абстрактный) метод */}Класс FigureFigureFigureFigure– абстрактный класс, его объекты нельзя заводить в памятиf; // нельзя*pf = new Figure; // нельзя*pf = new Line; // можноОднако, чисто виртуальная функция может иметь тело (а может и не иметь) (его можно вызвать через ::)Другие языки.В Delphi можно заводить объекты абстрактных типов. Метод становится абстрактным, если после негонаписать abstract;В С# и Java есть модификатор abstract, который можно указывать перед объявлением метода или класса(хотя компилятор может сам вставить этот модификатор).Ада:procedure Draw(F: figure) is abstract; - абстрактная процедура.Глава 3.
Интерфейсы.Интерфейс сделан для взаимодействия между объектамиA <-> BИнтерфейс как языковое понятие - набор операций, который можно выполнять с данными.• содержит объявления набора публичных методов• интерфейс не содержит членов данных (за исключением статических)• интерфейс может наследоваться (в т.ч. множественным образом)Существует связь между интерфейсом и абстрактным классом.В C++ интерфейсы моделируются с помощью абстрактных классов.В C#, Java - интерфейсы существуют явно.Delphi - существует такое понятие как interface COM, это не отдельное языковое понятие, а технологияMicrosoft.Проблемы в интерфейсах:1) Реализация (методов) интерфейса - бывает явная и неявная.2) Интерфейсы и виртуальные методы.Рассмотрим эти вопросы на примере С++Пример.
Класс с публичными виртуальными методами.class Interface {public:virtual void f()=0;virtual int g()=0;virtual ~Interpface(){};}Один метод все же может иметь реализацию - деструктор (с пустым телом). Это нужно для корректнойработы наследования. Если деструктор не виртуальный, то мы не можем пользоваться конструкциями типаdelete [].Интерфейсы в технологии COM.class IUnknown {public:virtual int QueryInterface( IID id, IUnknown **link)=0; //указатели вместоссылок для совместимости с Сиvirtual int AddRef()=0;virtual int Release()=0;}В технологии COM можно реализовывать подсчет ссылок, и при количестве ссылок на объект=0 удалятьего(реализуется это в Release() ).Другое применение интерфейсов в С++ - контракт.class ISet {public:virtual void Include(T&)=0;virtual void Exclude(T&)=0;//...}class BitScale { ...
}class SList { ... }class SetImpl:public ISetprivate SList {....};Все такие классы будут работать через интерфейс ISet.Интерфейсы - фактически понятие абстрактных данных в ОО концепции.В С#, Java интерфейсы вводятся с помощью ключевого слова interface. Интерфейс в java может содержатьтолько объявление методов и статических членов.interface IDrawing {void Draw();static int final SomeConst = -1;}Также могут содержаться другие классы.interface IMsg {class Message {...}void Send(Message m);}При наследовании класс либо должен полностью реализовать все методы интерфейса, либо бытьабстрактным.abstract class Recieving implements IMsg {public void Recieve(Message m) {...}}В языке С++ при множественном наследовании возникает множество таблиц виртуальных методов.В языке Java допускается неявная реализация методов.
Рассмотрим пример.Interface IDrawable {void Draw();}interface Card {void Draw();}class CardGame implements IDrawable, Draw {public void Draw {...} // какую именно семантику выбрать - это проблема}Невозможно сказать, к какому интерфейсу относится Draw, но его необходимо реализовать.В C#, Java, возможны ситуации, когда несколько раз реализуется одна и та же база (например,ромбовидное наследование).1) ромбовидное2)class Iclass Aclass Bclass Xclass Iclass Iclass Aclass Bclass Xinterface I {void f();}interface A implements I{ ...
};interface B implements I{ ... };class X implements A,B {..} //какое здесь наследование??? предлагается подумать самому.Интерфейсы-маркеры.Примеры:public Object Clone() {...}SerializibleПрограммист не может реализовать такие интерфейсы, их семантика защита в компилятор.С#interface Intf {void Insert(T x);int Const { get; }T this[ int ];event MyDelegate Ev;}C# более гибок чем Java, в нем допускается и явная и неявная реализация.// неявная реализацияinterface IDrawable { }I1: IDrawableI2: IDrawableclass X : I1, I2 {public void Draw() {...}};X x = new X();((I1)x).Draw();((I2)x).Draw();// явная реализацияclass X:I1,I2 {void I1.Draw(){...} // public нет => privatevoid I2.Draw(){...}}X x = new X();//При такой реализации просто писать x.Draw нельзя, т.к.
нет доступа.//Надо так:I1 i1 = (I1)x;i1.Draw(); // == I1.Draw();Можно также сделать так:class X:I1,I2 {void I1.Draw(){...} // public нет => privatevoid I2.Draw(){...}public void Draw() { ((I1)this).Draw() }}Теперь можно писать так:((I2)x).Draw()abstract class A {public abstract void f();}class NA:A {public void f(){...} // компилятор выдаст ошибку - нету new или override}Заметим, что в течение всего изложения в интерфейсах нигде не встречалось overridef();class Iclass Iclass I1class I2class XY: X {public void f() {...} // компилятор выдаст ошибку, т.к. f с одной сторонывиртуален, с другой "запечатан"}Компилятор потребует от нас написать public new void.Y y=newY();y.f();((X)y).f(); // будут вызваны разные методы.Т.е.
если мы реализовали интерфейс, то производные классы уже не могут менять реализацию (приходитсясоздавать новую иерархию)Трей Нэш пишет, что возможна некоторая путаница, и с ним сложно не согласиться :][КОНЕЦ]18dec08, 21:54.