Лекция №1. Введение

Вид материалаЛекция
Подобный материал:
1   2   3   4   5
Объявление классов в Delphi.


Описание (объявление) класса в Delphi для рассматриваемого примера имеет вид:


Unit Card;

Interface

Type

SUITS = (Heart, Club, Diamond, Spade);

COLORS = (Red, Black);

TCard = Class(Tobject)

Public

Constructor Create(I:integer, S:SUITS);

Function COLOR:COLORS;

Procedure DRAW(Wnd, X, Y:integer);

Function FaceUp:Boolean;

Procedure FLIP;

Function RANK:integer;

Function SUIT:SUITS;

Private

SUITABLE:SUITS;

RANKVALUE:integer;

FACEUP:Boolean;

end;

Implementation

end;

Родительский класс, от которого происходит наследование, указывается вслед за ключевым словом Class. Наиболее часто родительским классом является абстрактный системный класс TObject. При разработке Delphi – приложений принято соглашение, что начальная буква «Т» является признаком типа данных. Конструктор – это специальный метод, вызываемый при создании нового экземпляра класса – объекта. Ключевые слова public и private используются для разбиения описания класса на интерфейсную область (поля, доступные пользователям класса) и на реализацию (поля, которые используются только внутри класса и недоступны пользователям класса). Это очень мощное средство маскировки данных и методов от пользователей классов. Раздел Implementation, подобно Interface, может содержать подразделы с ключевыми словами Const, Var, Type, равно как и тела процедур и функций. Любые типы данных, определенные в этом разделе, используются только внутри блока. Фрагмент раздела Implementation:


Implementation

Const

CardWidth = 65;

CardHeight = 75;

Function Card.COLOR:COLORS;

begin

Case SUIT of

Diamond, Heart: COLOR:=Red;

Sprade, Club: COLOR:=Black

end

end;

.

.

end;


На переменные объекта можно ссылаться внутри метода как на обычные переменные. В отличие от традиционных языков программирования имена методов необязательно являются уникальными, и одно и тоже имя может использоваться в нескольких различных классах, в том числе и в пределах одного модуля. Поэтому при вызове метода требуется специальная синтаксическая конструкция для указания класса, к которому принадлежит метод. В Delphi эта конструкция состоит из имени класса, последующей точки и имени метода (селектор – функция, или квалификатор).


Объявление классов в языке C++.


Объявление классов в C++ также начинается с ключевого слова class.


enum suits {diamond, club, heart, spade};

enum colors {red, black};


class card {

public:

card(suits,int);

// Доступ к атрибутам карты:

colors color ();

bool faceUp();

int rank ();

suits suit ();


// Выполняемые действия:

void draw(win&, int x, int y);

void flip ();

private

bool faceup;

int r; // ранг

suits s; // масть

};

Ключевое слово public означает область интерфейса, то есть то, что видно извне класса. Ключевое слово private предшествует полям, доступ к которым разрешен только из самого класса.

Функция card(suit,int) в описании класса является уникальной. Ее имя совпадает с именем класса, и у нее нет возвращаемого значения. Это – функция конструктор, она используется при инициализации создаваемых экземпляров (объектов) класса.

Поскольку методы рассматриваются просто как поля специального вида, принадлежащие объекту и неразличимые от полей данных, метод и данные не могут иметь общего имени. Тем самым, переменная s хранит значение, представляющее собой масть карты, в то время как метод suit возвращает это значение. Аналогично, идентификаторы r и rank нужны для хранения и возврата ранга карты.

Файл реализации для рассматриваемого класса должен обеспечить работу методов, описанных в интерфейсном файле. Начало файла реализации имеет вид:


#include “card.h”

card::card(suit sv, int rv)

{

s = sv;

r = rv;

faceup = true;

}

int card::ranc()

{

return r;

}

Тело метода записывается как стандартная функция языка С++, но имени метода предшествуют имя класса и два двоеточия. На переменные объекта можно ссылаться внутри метода как на обычные переменные. Комбинация имени класса и имени метода образуют полное имя с помощью селектор - функции «.».

В языке С++ имеется возможность использования встроенных функций. Абстрагирование и инкапсуляция часто способствуют появлению большого количества функций, которые выполняют незначительную часть работы и, следовательно, имеют небольшой размер кода. Определяя их как встраиваемые функции, можно сохранить выгоды инкапсуляции и избежать затрат на вызов этих функций во время выполнения. Встраиваемая функция выглядит точно также, как и обычная, с теми же синтаксическими правилами. Разница состоит лишь в том, что компилятор преобразует вызов встраиваемой функции непосредственно в код в точке ее вызова, сокращая тем самым расходы на обращение к функции и возврат управления. Например:

inline int card::rank()

{

return r;

}


Если функция определяется в открытой интерфейсной части описания класса, то и все определение встраиваемой функции задается в интерфейсном файле, а не в файле реализации, например:


class card

{

public

card (suits, int);

// Доступ к атрибутам карты

int rank ()

{ return r; }

suits suit ()

{ return s: }

colors color ();

bool faceUp ()

{ return faceup; }

// Выполняемые действия

void draw (win&, int x, int y);

void flip ()

{ faceup = ! faceup; }

private:

bool faceup;

int r; // и т.д.

Лекция №4. Основные сведения о языке Java.


Язык программирования Java – это объектно-ориентированный язык, созданный в первую очередь как средство разработки приложений для Internet и World Wide Web. Его преимущество заключается в создании безопасных платформо–независимых приложений, которые могут использоваться в любых узлах Internet.

Java является очень мощным инструментом разработки приложений в сетевых средах. Кроме того, его можно рассматривать как универсальный язык программирования, подходящий для создания самых разнообразных приложений, которые либо не зависят от сетевых средств, либо используют их нестандартным образом. Java обладает многими языковыми средствами, присущими большинству современных языков программирования. Он использует конструкции, схожие с языком «С++», но дополняет их другими средствами.

Программы на Java строятся только на основе классов, и в этом его коренное отличие от «С++» и Delphi. Исходный текст программы на Java компилируется в байт – код, выполняемый на виртуальной машине Java. Байт – код является универсальным языком, и именно он интерпретируется виртуальной машиной в каждой системе, которая поддерживает Java.

Виртуальная машина присваивает каждому приложению собственный контекст времени выполнения, который одновременно изолирует приложения друг от друга и обеспечивает безопасность работы. Менеджер безопасности каждого контекста времени выполнения определяет, какие возможности доступны данному приложению. Например, менеджер безопасности может запретить приложению операции чтения или записи на локальный диск или ограничить сетевые соединения строго определенным компьютером. В совокупности все эти средства делают язык Java полностью платформо – независимым. Исходный текст Java, скомпилированный в байт – код Java, может выполняться на любом компьютере, где имеется виртуальная машина Java.

Как и любом другом языке программирования, в Java имеются встроенные (примитивные) типы данных, а именно:
  • boolean (true или false);
  • char 16-ти разрядный символ в кодировке Unicode 1.1;
  • byte 8-ми разрядное целое со знаком;
  • short 16-ти разрядное целое со знаком;
  • int 32-х разрядное целое со знаком;
  • long 64-х разрядное целое со знаком;
  • float 32-х разрядное вещественное число;
  • double 64-х разрядное вещественное число.


Unicode – это новый международный стандарт для набора символов. Символы Unicode состоят из 16-ти бит, благодаря чему обеспечивается поддержка букв, входящих в большинство языков мира.

Набор символов Java также составляют символы Unicode, в отличие от большинства языков программирования. В настоящее время окружение Java может читать стандартные ASCII - коды и автоматически преобразовывать их в Unicode.

Комментарии в Java трех видов:
  • // Комментарий - игнорируются слова от // до конца строки;
  • /* Комментарий */ - игнорируются символы между /* и */, включая завершающие символы строк типа \r и т. п.
  • /** Комментарий / - игнорируются символы от /** до */, аналогично вышеуказанным.


Лексемы в Java – это слова, из которых состоят программы. Лексемы разделяются символами – разделителями, (пробел, знак табуляции). Идентификаторы в Java должны начинаться с буквы, символа «подчеркивания» или знака «доллар», за которыми следуют алфавитно-цифровые символы в произвольном порядке. Идентификаторы могу иметь любую длину. В качестве идентификаторов не могут использоваться зарезервированные слова.

Для каждого типа данных Java определяются понятия литералов, которые представляют собой постоянные значения данного типа. Литералы – это неименованные константы. Для ссылок на объекты существует всего один литерал – null. Null не относится ни к одному из типов. Логические значения - это true или false.

Целые значения являются последовательностями восьмеричных, десятичных или шестнадцатеричных цифр. Начало константы определяет систему счисления: 0 – восьмеричное число, 0Х - означает шестнадцатеричное число, любое другое число указывает на десятичное число. Целые константы относятся к типу long, если заканчиваются на L или l.

Значения с плавающей точкой представляются в виде десятичного числа с необязательной десятичной точкой, за которой необязательно может следовать порядок. В конце числа может стоять символ F или f для обозначения константы с ординарной точностью, и D или d для обозначения двойной точности.

Символьные константы заключаются в апострофы. Некоторые служебные символы могут представляться в виде ESC – последовательностей, как в «С++».

Строковые литералы заключаются в двойные кавычки. В них могут входить любые ESC – последовательности, допустимые в символьных константах. Строковые константы являются объектами класса string.

Объявление переменных.


В объявлении указывается тип переменной, уровень доступа к ней и другие атрибуты идентификатора. Объявление переменной состоит из трех частей: вначале приводится список модификаторов, за ним следует тип переменной, в завершении следует список идентификаторов. Модификаторы могут отсутствовать в объявлении переменной. Например:

public static float [] x, y; .

Массив представляет из себя упорядоченный набор элементов. Элементы массива могут иметь примитивный тип или являться ссылками на объекты, в том числе ссылками на другие массивы. При объявлении переменной – массива ее размер не указывается. Количество элементов массива задается при его создании, при помощи оператора new, а не при объявлении. Размер объекта – массива фиксируется при его создании и не может изменяться в дальнейшем, например:

int [] ia = new int [3]; .

Объявляется массив с именем ia, в котором изначально хранится три целых значения.

Фундаментальной единицей программирования в Java является класс. Основными компонентами класса являются поля (данные) и методы (код для работы с данными). Код класса всегда может обращаться ко всем полям и методам данного класса. Для управления доступом к ним из других классов члены класса могут объявляться с одним из четырех атрибутов доступа:
  • Открытый (public). К членам класса всегда можно обращаться из любого места, в котором доступен сам класс;
  • Закрытый (private). К членам класса доступ осуществляется только из самого класса;
  • Защищенный (protected). К членам класса доступ разрешается только из подклассов и функций, входящих в тот же пакет.
  • Пакетный. Доступ к членам класса, указанным без атрибутов доступа, осуществляется только из того же пакета.

Классы в Java всегда объединяются в пакеты. Имя пакета задается всегда в начале файла:

package com.sun.games;

Предыдущий пример на языке Java имеет следующий вид:


class Card

{ // статические переменные

final public int [] red =0;

final public int [] black=1;

final public int [] spade=0;

final public int [] heart=1;

final public int [] diamond=2;

final public int [] club=3;

// Поля данных

private boolean[] faceup;

private int [] r;

private int [] s;

// Конструктор

Card (int sv, int rv)

{ s=sv; r=rv; faceup=false; }

// Доступ к атрибутам карты

public int rank ()

{return r;}

public int suit ()

{return s; }

public int color ()

{ if ( suit () == heart || suit () == diamond )

return red;

return black;

}


public boolean faceUp ()

{ return faceup; }

// Выполняемые действия

public void draw ( int x, int y)

{…….}

public void flip ()

{ faceup = ! faceup; }

}

Видно, что описание класса на языке Java очень похоже на описание класса в языке «С++», за исключением следующего:
  1. Отсутствует препроцессор, глобальные переменные, перечисляемые типы данных. Символьные константы могут быть созданы путем описания и инициализации локальных переменных с использованием ключевого слова final. Такие терминальные (окончательные) значения не могут впоследствии изменяться и оказываются эквивалентными символьным константам.
  2. Реализация методов производится непосредственно внутри определения класса, а не где – либо в другом месте. Это разрешено и в «С++», но в качестве опции, но для Java является обязательным.
  3. Вместо разбиения описания класса на разделы private и public эти ключевые слова присоединяются в явном виде к каждому полю или методу.
  4. За исключением конструкторов, все методы должны иметь возвращаемое значение.


Рассмотренные примеры объявления классов на языках «С++», Java и Delphi показывают сходство структуры классов в этих языках. ООП сближает языки, ранее казавшиеся совершенно несовместимыми. Поэтому, изучив принципы ООП на одном каком – либо языке, легко перенести их на любой другой язык, имеющий возможности программирования в классах.

Здесь важно отметить, что языки Delphi и «С++» вообще говоря, могут обходиться и без построения классов и объявления объектов. Для этих языков ОПП – всего лишь расширение их возможностей. Язык Java в принципе не допускает никакого другого подхода, кроме как ООП. Пример простейшей программы на Java.


Лекция №5. Сообщения, объекты и инициализация.


Выше были рассмотрены структуры классов для различных языков программирования. Это было статическое описание объектов. Также было показано, что действия в ООП инициируются посредством передачи сообщений объекту – получателю, ответственному за действие.


Синтаксис пересылки сообщений.


Термин пересылка сообщений используется для обозначения динамического процесса обращения к объекту с требованием выполнить определенное действие. Пересылка сообщений отличается от обычного вызова процедуры:

  • Сообщение всегда обращено к некоторому объекту, называемому получателем, или адресатом.
  • Действие, вызываемое в ответ на сообщение, не является фиксированным и зависит от класса получателя. Различные объекты, принимая одно и то же сообщение, выполняют различные действия.

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

Эти понятия являются центральными для ООП.


Синтаксис пересылки сообщений в Delphi-Pascal.


В системе Delphi – Pascal пересылку сообщений называют поиском метода. Это запрос, посылаемый объекту, чтобы вызвать один из его методов. Выше было показано, что методы описываются при определении классов как поля данных в типе «запись». Отсюда следует, что стандартная синтаксическая конструкция с использованием селектор – функции «.», применяемая для описания полей данных в записи, расширена до вызова метода. Селектор сообщения, то есть текст, следующий за селектор – функцией, должен соответствовать одному из методов, определенных для данного класса. Таким образом, если идентификатор MyCard описан как объект класса Card, то следующее сообщение прикажет карте перевернуться:

MyCard.Flip;

Объект слева от селектор – функции является получателем сообщения. Справа от нее находится действие, которое необходимо выполнить над данным объектом, т. е., нужный метод. Если заданный метод объявлен как процедура, то в сообщении он должен использоваться как процедура. Если он объявлен как функция, то он должен использоваться как функция. Компилятор проверяет корректность пересылки сообщения. Если передается сообщение, которое не указано в объявлении класса объекта – получателя, то фиксируется ошибка компилятора. Внутри любого метода имеется предопределенный идентификатор Self (Self – переменная), который является полным 32-х разрядным указателем на объект, который делает вызов метода (т. е., на получатель сообщения). Он бывает полезен для разрешения конфликтов идентификаторов внутри метода. Пусть, например, имеется следующая структура данных, описывающая позицию указателя «мыши» на экране.

Type

Mouse_Stat = Record

Active:Boolean;

X,Y:integer;

Visible:Boolean

end;

и метод некоторого объекта:

Procedure Location.GoToMouse(MousePos:Mouse_Stat);

……………..

with MousePos do

begin

Self.X:=X;

Self.Y:=Y

end;

…………………

если в объекте Location тоже имеются поля Х и Y. Таких ситуаций следует избегать, но бывает, что внутри сложного метода целесообразно использовать оператор присоединения, поэтому приходится использовать Self – переменную. Delphi позволяет возвращать результат функции, присваивая его специальной переменной Result, а не идентификатору функции.


Синтаксис пересылки сообщений в С++.


В языке программирования С++ методы принято называть функциями – членами класса, а пересылка сообщений называется вызовом функции – члена. Описание класса идентично описанию структуры. Синтаксис вызова функции – члена аналогичен доступу к полям данных (переменным объекта). Синтаксическая форма состоит из получателя, за которым следует селектор – функция точка, селектора сообщения, который соответствует имени функции – члена, и списка аргументов в круглых скобках. Если MyCard описан как объект класса Card, то следующий оператор приказывает карте отобразить себя в окне в точке с заданными координатами 25 и 37:


MyCard.Draw(25,37);


Даже если аргументы не требуются, круглые скобки все равно нужны, чтобы отличить вызов функции – члена от обращения к полям данных, например:


If (MyCard.faceUp( ))

{…………}

else

{………….}


Компилятор проверяет правильность пересылки сообщения, обращаясь к описанию класса – получателя. Попытка передать сообщение, не являющееся частью класса, приводит к ошибке компиляции. Функция – член класса, описанная с типом void, может использоваться как оператор, т. е., как вызов процедуры. Функции – члены, которые имеют возвращаемое значение других типов, вызываются в соответствии с правилами языка «С++» и как операторы, и как функции, т. е., как процедуры и традиционные функции.

С каждым методом ассоциирована псевдопеременная, в которой указан получатель сообщения. В языке «С++» эта псевдопеременная называется this и является указателем на получателя, а не собственно получателем. Поэтому используется разыменование указателя (операция ) для пересылки последующих сообщений к тому же получателю. Например, метод color, который используется для определения цвета карты, может быть описан следующим образом:


Colors Card::color ( )

{

swith (this  suit( ) )

{ case heart:

case diamond:

return red;

}

return black;

}


Переменная this также часто используется, если внутри метода надо передать получателя сообщения в качестве аргумента другой функции, например:


void aclass::aMessage (bclass b, int x)

{ // передать самого себя в качестве аргумента

b  do_Something(this, x);

}

В языке «С++» можно опустить использование this в качестве получателя. Внутри тела метода вызов другого метода без явного указания получателя трактуется как сообщение для текущего получателя. Например:


Colors Card::color ( )

{

swith (suit ( ) )

{

case heart:

case diamond:

return red;

}

return black

}

Так обычно и поступают при написании методов на «С++».