Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
1
Добавлен:
24.09.2019
Размер:
522.24 Кб
Скачать

Вопрос 12) Создание нового экземпляра класса.

     Одна из возможностей передачи свойств нескольких классов другому классу - это создание экземпляров классов. Тогда возможно будет вызвать методы и переменные этих классов через вызов этих классов. Этот механизм не является в полном смысле слова механизмом наследования, однако он предусматривает передачу свойств одного класса (как бы суперкласса) другому (подклассу).

Чтобы создать экземпляр класса нужно воспользоваться оператором new:

MyNewClass mNewCl = new MyNewClass ();

Переменной mNewCl типа MyNewClass (напомню, что типом любого элемента может быть как встроенный тип, так и имя любого существующего класса).

В одном и том же классе можно создать несколько экземпляров одного и того же класса, присвоив его значения двум или нескольким переменным. В приведенном ниже примере создается два экземпляра класса Thread (подпроцессы):

Thread firstThread = Thread.currentThread ();

Thread secondThread = new Thread (this, "Second Thread");

Теперь чтобы вызвать, например, метод isAlexanderVanin класса MyNewClass (смотрите первый пример), нужно записать следующий код:

mNewCl.isAlexanderVanin ();

Оператор точка служит для отделения имени пакетов от имен вложенных пакетов и классов, входящих в пакет, а также имени класса от имени переменной или метода, принадлежащих этому классу.

13. Преобразование методов базового класса. Вызов методов базового класса.

Основные определения

Класс — это тип данных, описывающий устройство объектов и подразумевает некоторое поведение и способ представления.

Объект — это экземпляр некоторого класса.

Метод — это функция или процедура, принадлежащая какому-то классу или объекту.(поведение)

Наследование — это вид взаимодействия классов, при котором есть класс родитель и класс потомок.

1) Класс потомок наследует все методы и поля родителя;

2) Потомок может добавлять свои поля и методы или переопределять методы родителя.

В результате наследование часто необходимо переопределить методы, которые были в базовом классе. Под базовым классом понимается класс родителя. Полиморфизм — использование одного и того же имени для решения нескольких похожих, но разных по реализации задач. Например, метод "Ехать" объекта - экземпляра класса "Корабль" наверняка отличается от метода "Ехать" объекта класса "Машина".

С++

class Car

{

public:

double Benzin; // бензин

void Go( float dist )

{

Benzin -= dist / 10; // 1 литр бенза на 10 км

Rasst += dist; // проехали

}

protected: double Rasst; // пройденное расстояние};

class Truck : public Car

{

public int K;

void Go( float dist )

{

Benzin -= dist / 5; // 1 литр бенза на 5 км

Rasst += dist; // проехали

}

};

Стандартны следующие декларации объектов:

Car * car = new Car;

Truck * truck = new Truck;

Однако принцип полиморфизма допускает и такую запись:

Car * car = new Truck;

Переменная ссылочного, более общего типа допускает хранение ссылки на дочерний тип.

А вот запись Truck * truck = new Car;

будет ошибочной. Однако можно принудительно выполнить подобный оператор, если явно указать приведение типов:

Truck * truck = (Truck*)(new Car);

Здесь создается новый экземпляр класса Car, и ссылка на него приводится к типу ссылки на объект класса Truck. В результате в переменных car и truck будут храниться ссылки на объекты других классов! Переменая car хранит ссылку на объект-грузовик, наследник Car, а переменная truck хранит ссылку на экземпляр родительского класса Car.

Теперь зададим вызовы метода Go(), который имеется и в классе Car, и в классе Truck:

Car * car = new Truck;

car->Go(100);

Truck * truck = (Truck*)(new Car);

truck->Go(100);

Какие конкретно версии метода Go() будут вызваны - класса Car или Truck? Это и определяет принцип полиморфизма. В соответствии с ним в языке С++ определены так называемые статическое связывание и динамическое связывание. Связывание методов с объектом.

Статическое связывание - это связывание метода с родительским объектом на этапе компиляции. Так как компилятор не знает, как конкретно будет работать программа, он всегда исходит из известного и явно заданного типа объекта-владельца метода. Если используется переменная car класса Car, то будет вызван метод Go() класса Car, хотя физически в переменной car хранится экземпляр класса Truck.

Так же и в случае с переменной truck - хотя мы принудительно записали в нее ссылку на объект класса Car, компилятор об этом не знает и исходит из типа переменной truck - вызывает метод Go() класса Truck.

Динамическое связывание - это связывание метода с объектом, которое происходит во время работы программы. При этом нужный метод определяется уже не типом переменной-владельца, а реальным типом объекта, ссылку на который она хранит. Но такое связывание возможно только для так называемых виртуальных методов, - разделение типов методов нужно, чтобы подсказать компилятору, где какое связывание реализовывать.

Виртуальный метод - это обычный метод, в заголовке которого используется ключевое слово virtual. Например:

class Car

{

public: ...

virtual void Go( float dist )

{

...

}

}

Теперь метод Go() класса Car описан как виртуальный. Пусть имеются команды

Truck * truck = (Truck*)(new Car);

truck->Go(100);

Если бы метод Go() класса Car был невиртуальным, то выполнилось бы статическое связывание. Но в данном случае вызывается метод Go() класса Car, потому что переменная truck типа Truck хранит ссылку на экземпляр класса Car.

C#

Под полиморфизмом понимается возможность оперировать объектами, не обладая точными знаниями их типов.

В ООП понятие полиморфизм тесно связан с наследованием и интерфейсами.

Интерфейсы(функции с множеством элементов; четко определенные соглашения)

Типы(определяют на интерфейсы объектов и их реализации; переменные могут быть также типизированными)

void Poly(object o)

{

Console.WrieLine(o.ToString());

}

Приведенный пример представляет собой описание полиморфной функции Poly, которая выводит на монитор произвольный объект o, преобразованный к строковому формату (o.ToString())

Применения функции Poly:

Poly(25); Poly(“John”); Poly(3,14)

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]