русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Квалификация имен


Дата добавления: 2015-06-12; просмотров: 1129; Нарушение авторских прав


Квалификация имен используется для однозначного понимания указываемого имени.

Для квалификации имени могут использоваться следующие операторы: :: (оператор принадлежности); . (оператор доступа к члену класса посредством имени); -> (оператор доступа к члену класса через указатель).

 


 

Лекция #11: С++. Методы - члены класса. Дружественные классы и члены класса Описывается синтаксис и семантика определения методов-членов класса. Вводится понятие прототипа метода. Рассматривается назначение модификаторов доступа. Описывается механизм применения методов с переменным числом параметров, создание указателей на методы – члены класса.
Методы-члены класса В терминологии объектно-ориентированного программирования функции также называются методами или методами - членами класса, для того чтобы подчеркнуть, что конкретная функция является членом некоторого класса. По стандарту ANSI C, используемому компилятором Visual C++, любая используемая в модуле компиляции функция должна иметь прототип, включающий в себя тип функции, имя функции и список параметров с их типами. Прототип - это некоторое предварительное описание функции, заканчивающееся символом ;. Прототип функции должен быть вставлен во все модули компиляции, использующие функцию. Для небольших программ прототип функции обычно записывается в модуль компиляции. Для программ, создаваемых средствами Visual C++, и программ, состоящих из нескольких модулей, прототип функции указывается в заголовочном файле. Объявление функции должно однозначно соответствовать ее прототипу и может находиться в любом модуле компиляции (для которого доступен прототип функции). Прототип метода, являющегося членом некоторого класса, записывается в заголовочном файле, содержащем объявление класса в теле этого класса. Метод - член класса может иметь следующие модификаторы доступа:
  • public - общедоступный метод;
  • protected - метод, доступный только для членов и объектов данного класса и наследуемых классов (наследуемых с модификаторами доступа public или protected);
  • private - защищенный метод, доступный только внутри класса.
Прототип метода может иметь следующее формальное описание: модификатор_доступа тип_метода имя_метода (список_параметров); Объявление метода может иметь следующее формальное описание: модификатор_доступа тип_метода имя_метода (список_параметров) { тело_метода } Тип метода является типом возвращаемого методом значения и может быть любым допустимым базовым или производным типом, включая и тип указателя. Указатели типа void могут использоваться для объявления параметров метода в том случае, если тип этих параметров на момент компиляции неизвестен. Например: void Fx(void *pV); //Прототип метода...piVar=new int;pfVar=new float;Fx(piVar); // Вызов метода для // параметра типа intFx(pfVar); // Вызов метода для // параметра типа float...// Реализация методаvoid Fx(void *pV) {*pV=12345;} Метод, возвращающий указатель, записывается следующим образом: тип *имя_метода(список_параметров). Список формальных параметров - это значения, передаваемые в функцию. Каждый элемент этого списка может иметь любой допустимый тип. Язык C++ допускает передачу параметров по значению и по ссылке или указателю. Параметры, передаваемые по значению, при выполнении программы заносятся в стек, и для больших размеров структур или массивов может возникнуть ситуация переполнения стека. Параметры, передаваемые как ссылки или указатели, не копируются в стек. Изменение значений самих параметров происходит только для параметров, переданных по ссылке или указателю. При передаче параметра по значению метод изменяет не сам параметр, а его копию. Список параметров может включать параметры, имеющие значения по умолчанию. Такие параметры указываются в конце списка параметров. Значение по умолчанию будет использовано только в том случае, если число переданных параметров меньше числа указанных формальных параметров в описании метода. Язык C++ разрешает рекурсивный вызов методов. В методах класса можно использовать ключевое слово this, являющееся указателем на объект данного класса. Это ключевое слово нельзя использовать вне метода члена класса. Создание метода-члена класса Для того чтобы в среде Visual Studio .NET добавить в класс новый метод - член класса, следует в окне просмотра классов Class View выделить секцию с именем класса и выполнить команду контекстного меню Add|Add Function, а затем в диалоге - мастере построения метода ввести имя метода, его тип, а также определить список параметров. При добавлении метода - члена класса в файл реализации класса автоматически добавляется код реализации нового метода, а в заголовочный файл - объявление этого метода. Методы с переменным числом параметров Метод может иметь переменное число параметров: это указывается в конце списка параметров символом многоточия ... . Методы с переменным числом параметров должны иметь как минимум один описанный формальный параметр. Для применения переменного числа параметров можно использовать:
  • макрос va_start(указатель_списка_параметров,последний_параметр) - при инициализации указателя и установке его на начало переменного списка параметров;
  • макрос va_arg(указатель_списка_параметров,i) - при выборе параметра и продвижении указателя в соответствии с его типом на следующий параметр;
  • макрос va_end((указатель_списка_параметров) - при установке указателя на список параметров, равный null, после извлечения значений всех параметров;
  • тип va_list - для создания указателя на список параметров.
Например: #include <stdio.h> // Библиотека, содержащая тип va_list#include <varargs.h>#include <iostream>int Fx ( int i1, ... ); // Прототип Функции с переменным // числом параметровvoid main( void ){ // Вызов функции Fx с различным // числом параметровstd::cout<< Fx ( 100, 200) );std::cout<< Fx ( 5 ) );std::cout<< Fx ( -1,-3,45 ) );}int Fx ( int i1, ... ) // Реализация функции с переменным // числом параметров{ int sumx,i; sumx = 0, i = i1; va_list list1; // Список параметров va_start(list1, i1 ); // Инициализация списка параметров while( i != -1 ) { sumx += i; i = va_arg(list1, int); //Извлечение следующего параметра } va_end(list1); return( sumx );} Указатели на методы-члены класса и на функции Указатели на методы и на функции могут быть использованы для передачи метода в качестве параметра другому методу. Объявление указателя на метод может иметь следующее формальное описание: тип_метода (имя_класса::*имя_метода_указателя) (список параметров);тип_функции (*имя_ функции_указателя) (список параметров); Инициализация указателя может иметь следующее формальное описание: тип_метода имя_класса::*имя_метода_указателя (список параметров)= &имя_класса::имя_любого_метода;тип_функции (*имя_ функции_указателя) (список параметров)= &имя_функции; Вызов метода, объявленного как указатель на метод, может быть выполнен следующим образом: (имя_объекта->*имя_ метода_указателя) (список параметров);(*имя_ функции_указателя)(список параметров); Для функций, но не для методов - членов класса, разрешена другая форма вызова метода: имя_ функции_указателя(список параметров);(имя_ функции_указателя)(список параметров); Объявление функции, имеющей в качестве параметра указатель на метод, может иметь следующее формальное описание: тип_метода имя_метода (тип_метода_указателя (*имя_метода_указателя) (список параметров)); Вызов метода, использующего в качестве параметра указатель на метод, может иметь следующее формальное описание: имя_метода(имя_объекта->*имя_метода_указателя);имя_функции(имя_функции_указателя); Разрешается создавать массив указателей на функции. При использовании указателей на функцию можно не употреблять операцию разыменования или операцию получения адреса. Например: class a1{public: a1(void); ~a1(void); int Fx1(int i1); int Fx2(int i2);};a1::a1(void){}a1::~a1(void){}int a1::Fx1(int i1){ return 1;}int a1::Fx2(int i2){ return 2;} int (*Fy_pointer)(); // Объявление указателя на функциюint Fy ();int _main(int argc, char* argv[]){ a1* a1Object = new a1(); int (a1::*Fx_pointer)(int)=&a1::Fx2; // Объявление и инициализация указателя // на метод - член класса int i; i=(a1Object->*Fx_pointer)(1); // Вызов по указателю на метод std::cout<<i; int (*Fy_pointer)()=&Fy; // Объявление и инициализация указателя // на функцию std::cout<<(Fy_pointer)(); std::cout<<(*Fy_pointer)(); // Вызов по указателю на // функцию (две формы) return 0;}int Fy () {return 5;} Встроенные функции Встроенные функции указываются оператором inline. Применение встроенных функций может несколько сократить время выполнения программы, так как компилятор встраивает код такой функции в том месте программы, где указан ее вызов. Например: inline void Fx(void) { std::cout<<"Функция Fx"<<std::endl;}...Fx(void); // Этот код будет заменен компилятором // на код встроенной функции Перегрузка функций и методов Язык C++ позволяет выполнять перегрузку функций и методов - членов класса, то есть вызывать функцию (метод) с тем же именем, но с различными типами фактических параметров. Для создания перегружаемой функции следует указать отдельный прототип и сделать отдельное объявление для каждого списка параметров. Если функции различаются только типом и имеют совпадающие списки параметров, то для таких функций перегрузка не допускается. Для определения вызываемой перегружаемой функции учитываются только списки параметров, а тип возвращаемого значения не учитывается. При этом для соответствия списка параметров вызываемой функции может применяться преобразование типов и соответствие по многоточию (соответствие по многоточию?) для функций с переменным числом параметров. Дружественные члены класса Дружественные члены класса (методы) позволяют получить доступ к защищенным модификатором private членам класса из методов других классов. Методы и классы, объявляемые дружественными, иногда также называются друзьями класса. Если метод класса A внутри тела класса B объявляется с модификатором friend, что указывает на то, что он является другом класса, то из него разрешен доступ ко всем членам класса B. Например: class A { public: int Fx();}class B { public: friend int A::Fx(); private:} Дружественные классы Объявление дружественного класса позволяет всем его методам получить доступ ко всем переменным и методам другого класса. Например: class A {public: int Fx();}class B {public: friend class A; private: } Дружественный класс или член класса будет доступен только в том случае, если он был объявлен в области видимости самого класса или ранее во внешней области видимости, внутри которой располагается область видимости, содержащая объявление класса с объявлениями друзей класса. Например: class A {public: // Класс расположен во внешней // области видимости int Fx1(); }namespace classB { class B {public: friend class A; friend class C; private: } class C { public: // Класс расположен в том же // пространстве имен int Fx2(); }} Дружественные классы не наследуются, и их дружественность не является транзитивной. Например: class A {int Fx();}class B {friend class A;}class C {friend class B;} // Класс А не является // дружественным классу Cclass D : public B {} // Класс А не является // дружественным классу D

 




 

Лекция #12: С++. Cтатические члены класса. Виртуальные функции Описывается объявление и инициализация статических членов класса. Рассматривается применение виртуальных функций, реализация механизмов раннего и позднего связывания. Вводится понятие абстрактного метода. Рассматривается применение шаблонов методов и шаблонов классов.
Статические члены класса Переменные и члены класса, объявленные с модификатором доступа static, называются статическими членами класса. Cтатические переменные и методы доступны без создания объекта данного класса. Имя статической переменной квалифицируется именем класса с использованием операции принадлежности :: , а не именем экземпляра класса. Например: class A { public: static int iStat; };int main(int argc, char* argv[]) { A:: iStat = 123;} Статические методы могут вызывать и использовать только другие статические методы и статические переменные. Из статического метода нельзя выполнять вызов не статического метода - члена класса. Статическую переменную можно рассматривать как аналог глобальной переменной, которая связана с конкретным классом. Часто статические переменные называют переменными класса, а не статические переменные - переменными экземпляра. Для статических переменных могут использоваться указатели. Например: class A{ public: static int iStatVar; };int main(int argc, char* argv[]){int A:: iStatVar = 0;int *piStatVar = &A:: iStatVar;} При использовании статических переменных указатели всегда являются указателями на существующий тип (в данном примере на тип int), а не на тип класса. Для того чтобы создать и использовать статическую переменную, следует:
  1. Объявить (как правило, в заголовочном файле) статическую переменную как член класса.
Например: static int iStat;.
  1. Для выделения памяти под эту переменную ее повторно следует объявить в модуле компиляции, в котором она будет использоваться, квалифицируя имя статической переменной именем класса.
Например: int A::iStat;
  1. Выполнить инициализацию статической переменной (по умолчанию статическая переменная типа int имеет значение 0).
Например: A::iStat=123; Инициализацию статической переменной можно выполнять в теле конструктора в том случае, если при создании объекта с использованием этого конструктора память под статическую переменную уже выделена. Однако инициализировать статическую переменную через конструктор в форме имя_класса::имя_конструктора : имя_стат_переменной(значение) { } нельзя ни в каком случае. Для того чтобы создать статический метод - член класса в среде Visual C++, достаточно выделить в окне Class View секцию с именем класса, в который будет вставлен создаваемый метод, и выполнить команду контекстного меню Add|Add Function. А затем определить тип и имя создаваемого метода, список параметров, и отметить флажок Static, указывающий на то, что создаваемая функция будет статической. В результате выполненных действий среда Visual C++ добавит в заголовочный файл класса прототип создаваемой статической функции, а в файл реализации - код реализации создаваемой статической функции. Например: class A{public: a1(void); ~a1(void); int Fx1(int i1); int Fx2(int i2); protected: static int Fstat1(void); // Статическая функция доступна //только для статических методов - членов //данного класса и наследуемых классовpublic: static int Fstat2(void); // Общедоступная статическая функция}; int main(int argc, char* argv[]){std::cout<<a1::Fstat2(); // Вызов статической функции} Реализация статической функции записывается так же, как и реализация любого другого метода - члена класса. При этом ключевое слово static не указывается. Например: int A::FStat1(void) { return 0; } Виртуальные методы Виртуальные методы объявляются в базовом классе с ключевым словом virtual, а в производном классе могут быть переопределены. Прототипы виртуальных методов как в базовом, так и в производном классе должны быть одинаковы. Применение виртуальных методов позволяет реализовывать механизм позднего связывания, при котором определение вызываемого метода происходит на этапе выполнения, а не на этапе компиляции. При этом вызываемый виртуальный метод зависит от типа объекта, для которого он вызывается. При раннем связывании, используемом для не виртуальных методов, определение вызываемого метода происходит на этапе компиляции. На этапе компиляции строится таблица виртуальных методов, а конкретный адрес проставляется уже на этапе выполнения. При вызове метода с использованием указателя на класс действуют следующие правила:
  • для виртуального метода вызывается метод, соответствующий типу объекта, на который указывает указатель.
  • для не виртуального метода вызывается метод, соответствующий типу самого указателя.
В следующем примере иллюстрируется вызов виртуальных методов: class A // Объявление базового класса{ public: virtual void VirtMetod1(); // Виртуальный метод void Metod2(); // Не виртуальный метод};void A::VirtMetod() { cout << "Вызван A::VirtMetod1\n";} void A::Metod2() { cout << "Вызван A::Metod2\n"; } class B : public A // Объявление производного класса{public: void VirtMetod1(); // Виртуальный метод void Metod2(); // Не виртуальный метод};void B::VirtMetod1() { cout << "B::VirtMetod1\n";}void B::Metod2() { cout << "B::Metod2\n"; }void main() { B aB; // Объект класса B B *pB = &aB; // Указатель на объект класса B A *pA = &aB; // Указатель на объект класса A pA->VirtMetod1(); // Вызов метода VirtMetod класса B pB->VirtMetod1(); // Вызов метода VirtMetod класса B pA->Metod2(); // Вызов метода Metod2 класса A pB->Metod2(); // Вызов метода Metod2 класса B} Пример 12.1. Вызов виртуальных методов Результатом выполнения этой программы будут следующие строки: Вызван B::VirtMetod1Вызван B::VirtMetod1Вызван A::Metod2Вызван B::Metod2 Чисто виртуальной функцией называется виртуальная функция, указанная с инициализатором =0. Например: virtual void F1( int) =0; Объявление класса может содержать виртуальный деструктор, используемый для удаления объекта определенного типа. Однако виртуального конструктора в языке С++ не существует. Некоторой альтернативой, позволяющей создавать объекты заданного типа, могут служить виртуальные методы, в которых выполняется вызов конструктора для создания объекта данного класса. Например: class A{public: A(); A (const A&); virtual A* virt_object1 () { return new A(); } virtual A* virt_object2 () { return new A(*this); }} Виртуальные классы Для того чтобы при множественном наследовании один и тот же базовый класс не порождал для объекта производного класса несколько объектов базового класса, при объявлении производного класса такой базовый класс указывается с ключевым словом virtual и называется виртуальным классом. Например: class A : virtual public B { } Абстрактные классы Абстрактным классом называется класс, который содержит хотя бы одну чисто виртуальную функцию. Абстрактный класс не может быть явно использован для создания объектов. Как правило, абстрактный класс применяется для описания интерфейса, который должен быть реализован всеми его производными классами. Если класс, производный от абстрактного класса, не содержит реализации всех его чисто виртуальных функций, то он также является абстрактным классом. Шаблоны методов Шаблоны методов позволяют описывать одинаковую реализацию для различных типов параметров. Шаблон метода позволяет описать одну реализацию метода для всех допустимых значений параметров. Фактически шаблон метода заменяет набор перегружаемых методов с различными типами параметров. Шаблон метода - это еще одно проявление полиморфизма языка С++. Шаблоны методов используют в качестве параметра тип переменной. В момент компиляции при вызове метода, не имеющего прототипа, выполняется поиск шаблона метода, из которого вызываемый метод может быть сгенерирован. Шаблон метода указывается ключевым словом template, за которым в угловых скобках указывается список типов, используемых для параметров функции и типа возвращаемого значения. Например: template <class T1> T1 Fx (T1 x, T1 y) {return x+y;} При использовании шаблона компилятор заменит для вызываемого метода тип шаблона на тип, указанный при вызове метода (T1 на int в следующем примере). Например: int i1=1;int i2=2; std::cout<<Fx(i1,i2); Шаблоны классов Шаблоны классов позволяют определить параметризированный тип. Шаблоны классов аналогично шаблонам функций позволяют на этапе компиляции создавать определения классов. Шаблон класса указывается ключевым словом template, за которым в угловых скобках указывается список типов для создания параметризированного класса. Имя шаблона класса указывается после ключевого слова class. Для создания объекта на основе шаблона класса после имени шаблона в угловых скобках указывается конкретный тип: имя_шаблона_класса <тип> имя_объекта. Например: template <class T1> // Описание шаблона классаclass A {T1 x,y;public: A(); ~A(); T1 Fx(); void Fy(T1 a, T1 b);};template <class T1> A< T1>::A() {} // Реализация методов шаблона классаtemplate <class T1> A< T1>::~A() {}template <class T1>T1 A< T1>::Fx(){ return x*y;}template <class T1>void A< T1>::Fy(T1 a, T1 b) {x=a; y=b;} int main(int argc, char* argv[]){ int i1=1; int i2=2; double x=1.5; double y=2.5; A <int> F1; // Создание объекта с использованием шаблона класса A <int> *pF1=&F1; // Указатель на объект параметризированного типа pF1->Fy(i1,i2); std::cout<<pF1->Fx()<<std::endl; A <double> F2; A <double> *pF2=&F2; pF2->Fy(x,y); std::cout<<pF2->Fx()<<std::endl; return 0;} Пример 12.2. Создание объекта на основе шаблона класса Работа с памятью Свободная память, которую можно заказывать в процессе выполнения программы, называется динамической памятью. Для выделения непрерывного блока памяти можно использовать функцию malloc(), а для освобождения - функцию free(). Прототипы этих функций расположены в заголовочном файле stdlib.h. Например: int *pIntBuffer;// Выделение памяти под 5 переменных типа intpIntBuffer=malloc(5*sizeof(int)); При отсутствии требуемого количества памяти функция malloc возвращает значение null. Выделение динамической памяти также можно выполнять оператором new, а освобождение - оператором delete. Оператор new автоматически учитывает тип объекта и выделяет требуемое количество памяти. Пример: double *pBuffer;// Выделение памяти под 10 переменных типа doublepBuffer=new double [10];

 


 

Лекция #13: Java. Механизмы наследования. Ссылочные типы данных. Интерфейсы. Вложенные классы Вводится понятие класса и интерфейса в языке Java. Рассматривается применение вложенных и абстрактных классов. Приводится пример реализации раннего и позднего связывания. Рассматривается эквивалентность объектов в языке Java.
Механизмы наследования Класс - это шаблон, в котором определяются данные и поведение объекта. Объекты одного класса совместно используют общую структуру данных и общее поведение. Объявление класса в языке Java создает новый ссылочный тип, определяющий как описание методов, так и их реализацию. Объявление интерфейса создает новый ссылочный тип, который специфицирует описание методов и имена некоторых констант, но не определяет саму их реализацию. Интерфейс может быть объявлен для расширения одного или нескольких интерфейсов. Наследование позволяет определять новые классы в терминах существующих классов. В языке Java поддерживается только простое наследование: любой подкласс является производным только от одного непосредственного суперкласса. При этом любой класс может наследоваться от нескольких интерфейсов. Наследование интерфейсов реализует некоторую замену множественному наследованию, когда вместо того чтобы один класс имел несколько непосредственных суперклассов, этот класс наследует несколько интерфейсов. Интерфейс позволяет определить некоторый шаблон класса: описание методов без их реализации. Язык Java разрешает несколько уровней наследования, определяемых непосредственным суперклассом и косвенными суперклассами. Наследование можно использовать для создания иерархии классов. При создании подкласса на основе одного или нескольких суперклассов возможны следующие способы изменения поведения и структуры класса:
  • расширение суперкласса путем добавления новых данных и методов;
  • замена методов суперкласса путем их переопределения;
  • слияние методов из суперклассов вызовом одноименных методов из соответствующих суперклассов.
Объявление класса Объявление класса вводит новый ссылочный тип и определяет или часть или всю его реализацию. При загрузке класса выделяется память для всех его статических переменных и затем выполняется их инициализация. Объявление класса может иметь следующее формальное описание: МодификаторыКласса class ИмяКласса extends ИмяСуперКласса implements СписокРеализуемыхИнтерфейсов {ТелоКласса} Тело класса содержит описание переменных, методов и вложенных классов и заключается в фигурные скобки. В частном случае тело класса может не содержать ни одного объявления. Например: public class A implements B { public A() { } public int Metod1(){return 0;}} interface B { public int Metod1();} Вложенный класс описывается так же, как и внешний. В описании каждого класса указывается имя класса и тело класса, содержащее объявления полей класса. Дополнительно для класса могут быть заданы модификаторы класса и указан непосредственный суперкласс и реализуемые классом интерфейсы. Полями класса в Java называются переменные и методы, определяемые в теле класса. Класс может иметь более одного модификатора класса. В языке программирования Java существуют следующие модификаторы класса:
  • abstract, являющийся модификатором реализации класса и определяющий, что класс может иметь абстрактные методы (методы, не имеющие реализации);
  • final, являющийся модификатором ограничения иерархии классов и указывающий, что класс не может иметь подклассов (не должен никогда появляться во фразе extends объявления класса). Класс с модификатором final обязан реализовать все свои интерфейсы.
  • public является модификатором доступа и указывает, что к данному классу разрешен доступ из других пакетов. Доступ может быть выполнен или непосредственно указанием квалифицированного имени класса, или с использованием оператора import.
Для указания модификаторов класса применяются следующие правила:
  • если класс, имеющий абстрактные методы, объявлен без модификатора abstract, то возникает ошибка компиляции;
  • для абстрактных классов нельзя создавать экземпляры класса;
  • если при объявлении класса не указан модификатор public, то класс доступен только внутри своего пакета;
  • при компиляции каждый общедоступный класс всегда записывается в отдельный файл с расширением .CLASS. Такой файл называется модулем компиляции;
  • имя общедоступного класса должно совпадать с именем файла, содержащего код класса на языке Java;
  • один модуль компиляции может содержать только один класс или интерфейс, имеющие модификатор public;
  • один модуль компиляции может одновременно содержать объявление общедоступного класса и нескольких интерфейсов или классов, не имеющих модификатора public;
  • один модуль компиляции не может одновременно содержать объявление общедоступного класса (public class) и общедоступного интерфейса (public interface);
  • объявление класса одновременно с модификаторами final и abstract вызывает ошибку компиляции.
Любой класс может иметь только один суперкласс, указываемый ключевым словом extends. Наследуемый суперкласс должен быть доступным классом и не иметь модификатора final. По умолчанию предполагается, что в том случае, если для класса не указано никакого суперкласса, то его непосредственным суперклассом станет класс Object из пакета java.lang, который всегда является корневым классом в любой формируемой иерархии классов. Раннее и позднее связывание Раннее и позднее связывание является одним из проявлений полиморфизма, позволяя выполнять одним оператором вызов различных методов в зависимости от типа объекта. В следующем примере оператор b.MyPrint() будет вызывать различные методы в зависимости от типа объекта, для которого он выполняется: class B{ void MyPrint () { }}class B1 extends B{ void MyPrint () { //Переопределение метода }}class B2 extends B{ void MyPrint () { //Переопределение метода }}class B3 extends B{ void MyPrint () { //Переопределение метода }}class PrintB{ B DoBObject () { // Метод, реализующий класс B B b; b= new B1(); … b= new B2(); … b= new B3(); … return b; }...B b= new PrintB.DoBObject(); b.MyPrint() // Выполняет вызов метода MyPrint в // соответствии с типом объекта b Объявление интерфейса Объявление интерфейса вводит новый ссылочный тип, членами которого являются константы и абстрактные методы. Реализация интерфейса всегда выполняется в классе, который использует данный интерфейс. Один класс может реализовывать несколько интерфейсов, и один интерфейс может использоваться несколькими классами. Интерфейсы позволяют разделять общую структуру - методы и константы, классами, не связанными между собой иерархией наследования. Объявление интерфейса может иметь следующее формальное описание: МодификаторИнтерфейса ИдентификаторИнтерфейса extends СписокНаследуемыхИнтерфейсов {ТелоИнтерфейса} Самым простым примером объявления интерфейса может быть следующий код: interface MyColors { int RED = 1, YELLOW = 2, BLUE = 4; } Интерфейс может иметь в качестве предков только интерфейсы. Интерфейс может иметь модификаторы public и abstract. Язык Java подразумевает, что каждый интерфейс по умолчанию имеет модификатор abstract, который не рекомендуется указывать явно. К интерфейсу, объявленному с модификатором доступа public, может быть произведен доступ из других пакетов, в противном случае - только из своего пакета. Тело интерфейса заключается в фигурные скобки и не может содержать конструктора или блоков инициализации статических переменных. В остальном тело конструктора идентично телу абстрактного класса. Любая переменная интерфейса по умолчанию считается переменной с модификаторами public, static и final и обязательно должна быть инициализирована константным выражением. Также каждая переменная в теле интерфейса неявно считается переменной с модификатором. Метод, объявленный в теле интерфейса, по умолчанию считается методом с модификаторами abstract и public. Объявление метода завершается точкой с запятой и не содержит тела метода, заключенного в фигурные скобки. Метод интерфейса не может иметь модификаторов final или static. Интерфейс можно использовать как ссылочный тип при объявлении переменных. Переменная или выражение типа интерфейса могут ссылаться на любой объект, который является экземпляром класса, реализующего данный интерфейс. Переменную типа интерфейса можно использовать только после присвоения ей ссылки на объект ссылочного типа, для которого был реализован данный интерфейс. Вложенные классы Проблемы, возникающие из-за отсутствия множественного наследования, частично можно решить с использованием вложенных классов. Если требуется, чтобы класс ClassA наследовал все доступные методы, включая и protected-методы, двух классов (класса ClassB и класса ClassC), то реализовать такую схему можно через вложенный класс. Класс ClassA создается производным от класса ClassB. Это позволит всем экземплярам класса ClassA вызывать protected-методы класса ClassB. В классе ClassA объявляется подкласс ClassFromC, производный от класса ClassC и переопределяющий все protected-методы класса ClassC, реализуя их как вызовы соответствующих методов из суперкласса. При такой реализации экземпляр класса ClassA получает доступ к protected-методам двух различных классов - своего суперкласса и своего вложенного класса. Абстрактные классы Абстрактные классы содержат набор методов, который должен быть реализован в производном классе. Абстрактные классы и абстрактные методы помечаются модификатором abstract. Если в подклассе абстрактного суперкласса не выполнена реализация всех абстрактных методов, то подкласс по умолчанию также является абстрактным. Приведение ссылочных типов В языке Java преобразование ссылочных типов может происходить в четырех контекстах:
  • приведение;
  • присваивание;
  • вызов метода;
  • выполнение арифметических действий.
Наиболее общим случаем является приведение. В языке Java объявление класса определяет одноименный ссылочный тип. Все переменные, имеющие ссылочный тип, указываемый именем класса, являются объектами. Тип такого объекта определяется оператором instanceof. Например: String str1;Object ObjectName;ObjectName =(Object) str1; // Приведение типа if (ObjectName instanceof String) { // Тип объекта String String str2 = (String) ObjectName ; System.out.println(str2); // Запись в стандартный поток // вывода значения строки, // указанной параметром str2} В рассмотренном примере тип объекта str1 сначала приводится к типу своего косвенного суперкласса Object, а затем оператором instanceof определяется непосредственный тип объекта (при определении оператором instanceof типа объекта ObjectName как String или Object возвращается значение true). При приведении ссылочных типов действуют следующие правила:
  • объект всегда может быть приведен к типу своего непосредственного суперкласса;
  • приведение ссылочных типов может выполняться по иерархии классов сколь угодно глубоко;
  • любой класс ссылочного типа всегда можно привести к типу Object.
После приведения объекта к типу суперкласса все переменные и методы самого класса объекта становятся недоступными для приведенного объекта. Преобразование присвоением происходит в том случае, когда применяясь к переменной и значению, преобразует значение к типу переменной. При преобразовании присвоением не требуется проверки времени выполнения. Значение простого типа не может быть присвоено значению ссылочного типа, как и значение ссылочного типа не может быть присвоено значению простого типа. Присвоение значений ссылочного типа переменным ссылочного типа не требует во время выполнения действий преобразования. Просто компилятор должен иметь возможность преобразовать тип значения времени компиляции к типу переменной. Например: public class A { int x, y; }public class ADerived extends A { int z; }public interface B { void setColor(int color);}public class AB extends A implements B { int color; public void setColor(int color) { this.color = color; }}class MyA{ public static void main(String[ ] args) { // Создание переменных ссылочного типа // и присваивание им значения: A p = new A(); p = new ADerived(); // Правильно: ADerived это // подкласс класса A ADerived p3d = p; // Ошибка // Присваивание значения переменной // типа Object: Object o = p; // Правильно: любой объект приводим // к типу Object int[ ] a = new int[3]; Object o2 = a; // Правильно: массив приводим к Object // Присваивание значения переменной // типа интерфейса: AB cp = new AB(); B c = cp; // Правильно: AB реализует интерфейс B // Присваивание значения переменной // типа массива: byte[ ] b = new byte[4]; a = b; // Ошибка: это массивы различных типов ADerived[ ] p3da = new ADerived[3]; A[ ] pa = p3da; // Правильно: ADerived подкласс класса A p3da = pa; // Ошибка, т.к. необходимо приведение }} Преобразование приведением является более общим: если преобразование возможно, то приведение может его выполнить. Часто следует явно указывать преобразование приведением, чтобы компилятор имел строгую информацию о типе объекта. Для любого типа значения времени компиляции всегда можно выполнить приведение к тому же самому типу. Это позволит точно указать, что результирующее значение будет иметь именно указанный тип. Приведением можно преобразовывать значения одного вычислимого типа к другому. Тип boolean не может быть приведен ни к какому другому типу. Значения простых типов не могут быть приведены к значениям ссылочных типов и наоборот. Эквивалентность объектов Для определения равенства различных объектов применяется метод equals. Метод equals реализован в классе Object и соответственно наследуем любым классом Java. Большинство классов переопределяет этот метод таким образом, что позволяет сравнивать на эквивалентность объекты конкретного класса. Например: class A { String objectName; A (String name) { objectName = name; } // Конструктор}public class MyA { public static void main (String args[ ]) { A A = new A("Class1"); // Создание экземпляра класса A A_eq = A; // Ссылка на существующий объект A A_clon = (A)A.clone; // Создание объекта методом clone A A_2 = new A("Class2"); // Сравнение объектов: if (A.equals(A_eq)) { } if (A.equals(A_ clon)) { } if (A.equals(A_ 2)) { } }} Выполнив приведенный пример, можно увидеть, что эквивалентными будут только экземпляр класса и объект, созданный как ссылка на данный экземпляр класса. А экземпляр класса и его клон, так же, как и различные экземпляры одного класса, не совпадают. Принадлежность объекта к конкретному классу проверяется с помощью оператора instanseof. Пакеты классов JDK Инструментальный набор JDK включает утилиты и пакеты классов. Собственно говоря, все стандартные возможности программирования на Java базируются на классах этого инструментального набора. JDK состоит из нескольких отдельных пакетов, иногда называемых библиотеками. Различные среды программирования, такие как JBuilder, предоставляют дополнительные пакеты классов. Среда JBuilder 8 Enterprise полностью поддерживает работу со всеми классами пакета JDK 1.4.

 


 

Лекция #14: Члены класса. Статические переменные и методы Описывается синтаксис и семантика объявления переменных в языке Java. Объясняется использование статических переменных. Рассматриваются определение и реализация методов и механизмы передачи параметров. Вводится понятие ссылки на текущий объект. Анализируется применение переопределяемых и перегружаемых методов.
Члены класса. Статические переменые и методы. Объявление переменных и методов класса Объявление переменных В языке Java при объявлении переменной - указании ее типа и имени - одновременно можно выполнить ее инициализацию. Для переменной могут быть указаны следующие модификаторы доступа:
  • public или protected, или private, - определяющие область видимости переменной;
  • static - указывает, что переменная является переменной класса, а не переменной экземпляра класса;
  • final - запрещает присвоение значений переменной вне тела класса, в котором она объявлена;
  • transient - указывает, что переменная не является частью постоянного состояния объекта;
  • volatile - определяет возможность асинхронного изменения переменной.
Переменная, не имеющая модификатора static, называется переменной экземпляра. Переменная экземпляра создается для каждого нового экземпляра класса. Переменная, имеющая модификатор static, называется переменной класса. Для всех экземпляров класса существует только одна переменная класса. Эта переменная доступна и до создания экземпляра класса. Переменная, имеющая модификатор final, должна быть инициализирована внутри тела класса, так как вне тела класса final-переменная является константой и ее изменение или инициализация запрещены. Модификатор transient нельзя использовать совместно с модификаторами final или static. Любая переменная может иметь модификатор доступа public (общедоступный), protected (защищенный) или private (скрытый). Для этих модификаторов определены следующие правила доступа:
  • public указывает, что данная переменная будет доступна везде, где доступен класс, в котором она объявлена;
  • protected указывает, что данная переменная будет доступна как внутри пакета, содержащего объявление класса, в котором она определена, так и внутри любого подкласса данного класса;
  • private указывает, что данная переменная не будет доступна нигде кроме тела класса, в котором она объявлена.
По умолчанию переменная считается доступной везде внутри пакета, содержащего класс, в котором она объявлена, и не недоступна ни в каком другом подклассе указанного класса в том случае, если подкласс содержится в другом пакете. Инициализация переменной означает присвоение этой переменной некоторого значения. В качестве значения инициализации могут выступать:
  • выражение;
  • массив, указываемый в фигурных скобках.
Если переменная объявлена с модификатором static, то инициализация выполнятся сразу при загрузке класса. Если объявляемая переменная является переменной экземпляра, то инициализация выполняется при выполнении метода-конструктора класса. Если объявляемая переменная является локальной переменной, то ее инициализация происходит при выполнении оператора объявления этой переменной. Например: int i1,i2;float f1 = 3.0;float dArray1 [] = new float [14];java.lang.String str1 = "no?iea"; Object oObj = str1 ; Exception e = new Exception ( ) ; Определение методов В языке Java определение метода включает его объявление и реализацию. Определение метода всегда указывается в теле класса. Метод может иметь модификаторы доступа, возвращать значение и получать параметры. Метод может иметь следующие модификаторы:
  • public, protected или private -модификаторы доступа;
  • static - модификатор метода класса.
  • abstract, final, native или synchronized.
Для модификаторов доступа метода определены следующие правила:
  • public указывает, что данный метод будет доступен везде, где доступен класс, в котором он определен;
  • protected указывает, что данный метод будет доступен как внутри пакета, содержащего объявление класса, в котором он определен, так и внутри любого подкласса данного класса;
  • private указывает, что данный метод не будет доступен нигде кроме тела класса, в котором он определен.
По умолчанию метод считается доступным везде внутри пакета, содержащего класс, в котором он определен, и недоступным ни в каком другом подклассе указанного класса в том случае, если подкласс содержится в другом пакете. Метод, не имеющий модификатора static, называется методом экземпляра. Метод экземпляра может быть вызван только для созданного экземпляра класса или подкласса. Такой метод нельзя вызывать непосредственно, квалифицируя его именем класса. Метод, объявленный с модификатором static, называется статическим методом (или методом класса) и может быть вызван без создания экземпляра класса. Этот метод всегда вызывается непосредственно из класса. Статический метод имеет доступ к другим статическим переменным и методам данного класса. Если статический метод определен как final-метод, то он не может быть переопределен. Например: // Файл A.javapackage classa;public class A implements B { public A() { } static int b=1; public int Metod1(){return a;} public static int Metod2(){ return 0;} //Статический метод} interface B { final public static int a=1; // Статическая переменная int Metod1();} // Файл C.javapackage classa;public class C extends A { public C() { } static int b=3; public int Metod1(){return a;} public static int Metod2(){return 77;} public static void main(String[] args) { System.out.println(A.Metod2()); System.out.println(C.Metod2()); }} При переопределении методов их модификаторы доступа должны совпадать. Так, нельзя переопределить метод, имеющий модификатор доступа public, методом с модификатором доступа private. Абстрактный метод указывается модификатором abstract. Такой метод никогда не имеет тела метода: вместо фигурных скобок, ограничивающих тело метода, объявление метода завершается точкой с запятой. Абстрактные методы можно объявлять только в абстрактных классах или интерфейсах. Объявление абстрактного метода в классе, не имеющем модификатора abstract, приводит к ошибке компиляции. Любой подкласс абстрактного класса, который сам не является абстрактным классом, должен определять реализацию всех наследуемых не реализованных абстрактных методов. Например: public class A extends AA implements B { public A() { } public int Metod1(){return 0;} public static int Metod2(){return 0;} int Metod3(){return 0;} public int Metod4(){return 0;}} interface B { int Metod1(); abstract int Metod4();} abstract class AA{ abstract int Metod3(); } Методы, объявленные с модификатором private, не могут быть абстрактными методами, так как они недоступны вне тела класса. Статические методы также не могут выступать в качестве абстрактных методов, так как считаются конечными и не могут быть переопределены. Объявление метода с модификатором final запрещает его последующее переопределение. Такие методы называются конечными методами, и по умолчанию считается, что private-метод всегда является конечным методом. Методы, объявленные с модификатором native, могут иметь реализацию на другом языке программирования. Эти методы используются для написания машинно-зависимого кода. native-методы в Java-программе не имеют тела метода. Synchronized-методы выполняются с блокировкой:
  • для метода класса выполняется блокировка класса,
  • для метода экземпляра - блокировка объекта.
Это позволяет предотвратить параллельный доступ к данным из различных потоков в многопоточном приложении. Метод может возвращать значение заданного типа. В этом случае:
  • перед именем метода указывается тип возвращаемого значения;
  • в теле метода присутствует оператор return, определяющий возвращаемое значение.
Если метод не имеет возвращаемого значения, то он должен быть объявлен с ключевым словом void, указывающим на отсутствие возвращаемого значения. Если в качестве возвращаемого значения должен быть использован массив, то после имени метода может быть указана пара квадратных скобок или список параметров и пара квадратных скобок. Передача параметров Список формальных параметров содержит упорядоченные и разделенные запятой описания параметров (тип параметра и идентификатор параметра). Если метод не имеет параметров, передаваемых ему при вызове, то после имени метода указывается пара пустых скобок. В языке Java все параметры передаются по значению. При передаче параметра ссылочного типа его значением является ссылка на объект, поэтому в метод передается ссылка на экземпляр класса. Параметры в языке Java рассматриваются как локальные переменные метода, специфицированные вне тела метода. При вызове метода перед его выполнением происходит вычисление выражений, представляющих фактические передаваемые методу параметры, и присвоение вычисленных значений соответствующим локальным переменным (формальным параметрам). Ссылка на текущий объект При вызове метода экземпляра ключевое слово this
  • указывает ссылку на текущий объект. Это может быть использовано для передачи самого объекта в качестве аргумента методу самого экземпляра класса;
  • используется для указания квалифицированной ссылки на поля (переменные и методы) экземпляра класса.
Ключевое слово super используется для указания квалифицированной ссылки на поля (переменные и методы) суперкласса. По умолчанию любой метод первоначально ссылается на свои собственные переменные и методы и только в случае их отсутствия выполняется поиск этих полей вверх по иерархии суперклассов. При этом, если метод не переопределяется, то его имя не обязательно квалифицировать. Например: class A { public int a;}class B extends A { public int a, b; public void Metod1 ( ) { b=a; // Ссылка на this.a b=super.a; }} Имя суперкласса может быть использовано для квалифицированного доступа к статическим переменным или методам. Переопределение метода Переопределением метода называется объявление в подклассе метода, у которого имя, тип и список параметров, в точности совпадают с соответствующими атрибутами метода, ранее объявленного в суперклассе. При переопределении метода использование модификаторов доступа должно удовлетворять следующим условиям:
  • если переопределяемый метод суперкласса не содержит ни одного из модификаторов доступа public, protected или private, то переопределяющий метод не должен иметь модификатора private.
  • если переопределяемый метод суперкласса имеет модификатор доступа protected, то переопределяющий метод должен иметь модификатор доступа public или protected.
  • если переопределяемый метод суперкласса имеет модификатор доступа public, то переопределяющий метод должен также иметь модификатор доступа public.
Тип возвращаемого значения переопределяющего метода должен совпадать или преобразовываться присвоением к типу возвращаемого значения переопределяемого метода. Если класс содержит переопределяющий метод, то переопределенный метод можно вызвать только с квалификацией ссылки ключевым словом super или именем суперкласса (для статических членов). Например: class A { public void Metod1() { } public static void Metod2() { } }class B extends A {public Metod1() { } ...Metod1(); // Вызов метода из класса Bsuper.Metod1(); // Вызов метода из класса AA.Metod2();} Перегружаемые методы Перегружаемыми методами называется группа методов с одинаковым именем, но различными списками параметров. Язык Java позволяет определять в классах перегружаемые методы. Конструкторы Конструктором называется метод, вызываемый для инициализации объекта при его создании. Имя конструктора всегда совпадает с именем класса. Конструктор не может использовать оператор return и для него не указывается никакого типа возвращаемого значения. При объявлении конструктора можно указать модификаторы доступа public, protected или private. Наличие явно описанного конструктора в классе не является обязательным. В этом случае при создании объекта используется конструктор по умолчанию. Такой конструктор не получает параметров и вызывает непосредственно конструктор суперкласса: super(). При этом, если суперкласс не имеет конструктора без списка параметров, то происходит ошибка компиляции. Конструкторы не наследуются подклассами. Тело конструктора заключается в фигурные скобки. При этом первыми операторами должны быть указаны, если они используются, операторы вызова конструкторов данного класса или суперкласса. Конструктор может иметь следующее формальное описание: ИмяКласса (СписокПараметров) { ВызовКонструкторов БлокОператоров } Вызов конструкторов выполняется операторами this и super с указанием в скобках списка параметров. Например: public class C extends A { public C() {this(1,20); } // Вызов конструктора данного класса public C(int i, int j) { }} Вызов конструкторов подчиняется следующим правилам:
  • при создании объекта любого заданного класса будет неявно выполнена цепочка вызовов всех конструкторов его суперклассов;
  • первым будет выполнено тело конструктора для Object;
  • каждый последующий конструктор в цепочке будет выполняться только после выполнения конструктора своего непосредственного суперкласса;
  • при создании объекта будут инициализированы все переменные экземпляра.
Создание объекта При создании объекта последовательно выполняются следующие действия: вызывается конструктор, создается новый объект указанного типа, и все переменные экземпляра инициализируются своими значениями по умолчанию, затем формируется ссылка на созданный и инициализированный объект. Эта ссылка и является значением выражения, создающего объект. Объект может быть создан вызовом метода newInstance. В этом случае используется конструктор без списка параметров. Статические переменные Для каждого класса создается только один экземпляр статической переменной (переменой класса). При описании статических переменных должны быть выполнены следующие правила:
  • статические переменные должны быть объявлены вне всякого метода;
  • статические переменные могут быть инициализированы при их объявлении или блоком кода, отмеченного ключевым словом static, и также расположенным вне метода.
Инициализация статических переменных выполняется при загрузке класса. Инициализация переменных выполняется в порядке их следования в объявлении класса. Например: public class C { public C() { } static int b=3; static int c; static { b++; c = 10; } // Инициализация статической переменной} При инициализации статических переменных можно вызывать статические методы.

 



<== предыдущая лекция | следующая лекция ==>
Перечисления | ISBN 5-93286-003-0


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 2.343 сек.