Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка - Основи Програмування C_.doc
Скачиваний:
46
Добавлен:
18.12.2018
Размер:
1.44 Mб
Скачать

4. Посилання на екземпляри базового та похідних класів.

Важливо пам’ятати, що ідентифікатор, який ми вказуємо при визначенні екземпляру класу, є змінною-посиланням на область пам’яті, де буде розміщений об’єкт. Раніше ми використовували приведення типів при використанні змінних скалярних типів. Ці дії керувались низкою правил «просування по сходинках типів». З’ясуємо, як відбувається приведення типів при використанні посилань на екземпляри базового та похідних класів. Головне правило, яке тут діє, полягає у тому, що посиланню на базовий клас можна присвоїти посилання на будь-який похідний від нього клас. Тобто, якщо розглянути два класи – клас A та похідний від нього клас B, то правильність визначень та присвоєнь, виконаних у функції Main(), позначена у коментарях:

class A // базовий клас

{

// визначення базового класу

}

class B : A // похідний клас

{

// визначення похідного класу

}

static void Main()

{

A a = new A(); // вірно

A ab = new B(); // вірнопосиланню на базовий клас

// присвоєне посилання на похідний

B b = new B(); // вірно

B ba = new A(); // помилкапосиланню на похідний

// клас присвоєне посилання на базовий

a = b; // вірно посиланню на базовий клас

// присвоєне посилання на похідний

b = a; // помилка – посиланню на похідний

// клас присвоєне посилання на базовий

ab = b; // вірно

b = (B) ab; // вірно, явне приведеня

b = (B) a; // вірно, явне приведеня

a = (A) b; // вірно, явне приведеня

}

Дуже важливо розуміти, що саме тип змінної-посилання на клас, визначає доступні для використання члени класу. Тобто якщо змінній ab типу A присвоєне посилання на об’єкт B , як це зроблено в інструкції

A ab = new B(); то ab є змінною-посиланням на клас A, тому через ab доступні лише члени класу A, адже змінній базового класу невідомий склад похідних класів. Для більш прозорого розуміння цього факту розглянемо ще один приклад – варіацію на тему класів Base, SubBase та SubSubBase. Тут у кожний із класів даної ієрархії включене відкрите поле, щоб мати змогу прослідкувати за їх доступністю при використанні посилань на об’єкти даної ієрархії класів. Метод fun() перевантажений тричі – він приймає відповідно параметри типів Base, SubBase та SubSubBase. Результат цього прикладу підтверджує, що змінна b має тип Base, незважаючи на створення операцією new SubBase(200) , а змінна sb має тип SubBase, незважаючи на створення операцією new SubSubBase(300).

using System;

namespace ConvertObject

{

class Base // базовий клас

{

public int field;

public Base(int field_) // конструктор

{ field = field_; }

}

class SubBase : Base // похідний клас

{

public int subfield;

public SubBase(int field_) : base(field_)

{ subfield = field_; }

}

// похідний клас від похідного класу

class SubSubBase : SubBase

{

public int subsubfield;

public SubSubBase(int field_) : base(field_)

{ subsubfield = field_; }

}

class Program

{

static void fun(Base b)

{

Console.WriteLine("об\'єкт Base: field = {0}",b.field);

}

static void fun(SubBase b)

{

Console.WriteLine( "об\'єкт SubBase: field = {0}

subfield = {1}", b.field, b.subfield);

}

static void fun(SubSubBase b)

{

Console.WriteLine("об\'єкт SubSubBase: field = {0}

subfield = {1} subsubfield = {2}", b.field,

b.subfield, b.subsubfield);

}

static void Main(string[] args)

{

object o = new Base(100); // вірно - Base «Є» object

Base b = new SubBase(200); // вірно - SubBase «Є» Base

// вірно - SubSubBase «Є» SubBase

SubBase sb = new SubSubBase(300);

SubSubBase ssb = new SubSubBase(400); // вірно

// SubSubBase ssb = new Base(1000); // тут буде помилка

fun(b);

fun(sb);

fun(ssb);

}

}

}

В результаті роботи даного прикладу одержимо наступні повідомлення:

об'єкт Base: field = 200

об'єкт SubBase: field = 300 subfield = 300

об'єкт SubSubBase: field = 400 subfield = 400 subsubfield = 400

Цікаво також перевірити, що буде, якщо закрити коментарем метод fun(SubBase b), а потім і fun(SubSubBase b). Перевірте самостійно, яким чином будуть викликатись методи fun() .