C#. Доступ до елементів класу з екземплярів класів, що утворюють ієрархію. Особливості застосування посилання на базовий клас




Доступ до елементів класу з екземплярів класів, що утворюють ієрархію. Особливості застосування посилання на базовий клас. Ключові слова as, is. Способи виклику методів з однаковими іменами в ієрархіях успадкування. Статичний поліморфізм

У даній темі вивчається:

  • доступ з допомогою екземплярів до елементів класів, які утворюють ієрархію;
  • доступ до з допомогою посилання на базовий клас до елементів класів, що утворюють ієрархію;
  • вивчення особливостей використання ключових слів is, as;
  • способи виклику методів, які мають однакові імена в ієрархії класів.

Зміст


Пошук на інших ресурсах:

1. Використання екземплярів класів, що утворюють ієрархію. Особливості доступу до елементів базового класу з екземпляру успадкованого класу

Якщо класи утворюють ієрархію успадкування, то можна оголошувати об’єкти (екземпляри) кожного з класів ієрархії. Виключення стосується тільки абстрактних класів та інтерфейсів, екземпляри яких неможливо оголосити.
Якщо оголошено екземпляри різних класів, то з допомогою цих екземплярів можна отримати доступ до public-елементів цих класів. Якщо деякий клас є успадкованим з іншого класу, то з екземпляру цього класу можна отримати доступ:

  • до усіх public-елементів даного класу;
  • до тих public-елементів базового класу, імена яких не “ховаються” (перекриваються) елементами даного класу.

З екземпляру класу неможливо отримати доступу до елементів класів, успадкованих від даного.

Рисунок 1 демонструє доступ з екземплярів objA, objB, objC класів A, B, C що утворюють ієрархію успадкування. З кожного екземпляру робиться спроба викликати методи його класу та методи інших класів ієрархії.

C#. Спадковість. Доступ до елементів класів з екземплярів цих класів

Рисунок 1. Доступ до елементів класів з екземплярів цих класів

 

2. Приклад, що демонструє доступ з екземплярів класів, що утворюють ієрархію

Нижче наводиться текст демонстраційної програми яка відповідає рисунку 1. Програма створена за шаблоном Console Application.

using System;
using static System.Console;

namespace C_sharp
{
  // Клас A - базовий клас
  class A
  {
    public void Show()
    {
      WriteLine("Method A.Show()");
    }

    public void ShowA()
    {
      WriteLine("Method A.ShowA()");
    }
  }

  // Клас B - успадкований клас від класу A
  class B : A
  {
    public new void Show()
    {
      WriteLine("Method B.Show()");
    }

    public void ShowB()
    {
      WriteLine("Method B.ShowB()");
    }
  }

  // Клас C - успадкований з класу B
  class C : B
  {
    public new void Show()
    {
      WriteLine("Method C.Show()");
    }

    public void ShowC()
    {
      WriteLine("Method C.ShowC()");
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Екземпляри (об'єкти) класів A, B, C
      A objA = new A();
      B objB = new B();
      C objC = new C();

      // 2. Доступ до елементів з допомогою objA
      objA.Show(); // викликається A.Show()
      objA.ShowA(); // викликаєтья A.ShowA()
      // objA.ShowB(); - помилка, немає доступу: базовий клас не може
      // розширитись до можливостей похідного
      // objA.showC(); - помилка, також немає доступу

      WriteLine("-------------------");

      // 3. Доступ до елементів з об'єкту objB класу B
      objB.Show(); // за замовчуванням викликається B.Show(), тому що
      // метод B.Show() ховає (перекриває) метод A.Show()
      objB.ShowA(); // виклик методу базового класу A.ShowA()
      objB.ShowB(); // B.ShowB()
      // objB.ShowC(); - помилка, немає доступу: базовий клас не може
      // розширитись до можливостей похідного класу
      WriteLine("-------------------");

      // 4. Доступ до елементів з об'єкту objC класу C
      objC.Show(); // C.Show() - даний метод перекриває методи базових класів
      objC.ShowA(); // A.ShowA()
      objC.ShowB(); // B.ShowB()
      objC.ShowC(); // C.ShowC()
    }
  }
}

Результат виконання програми

Method A.Show()
Method A.ShowA()
-------------------
Method B.Show()
Method A.ShowA()
Method B.ShowB()
-------------------
Method C.Show()
Method A.ShowA()
Method B.ShowB()
Method C.ShowC()

 

3. Посилання на базовий клас в ієрархії класів. Особливості застосування

Як відомо, на будь-який клас може бути оголошене посилання. Якщо класи утворюють ієрархію успадкування, то для цих класів можна визначити наступне правило (правило 1): посиланню на базовий клас можна присвоїти значення екземпляру (об’єкту) похідного класу.

Тобто, після того як оголошене посилання на базовий клас, цьому посиланню можна присвоювати значення об’єкту (екземпляру) будь-якого класу з ієрархії. Таким чином, можна “рухатись” з допомогою посилання по створеним екземплярам класів з ієрархії.

Рисунок 2 демонструє правило 1 на прикладі ієрархії з 3 класів A, B, C.

C#. Спадковість. Присвоєння посиланню на базовий клас значень екземплярів похідних класів

Рисунок 2. Присвоєння посиланню на базовий клас значень екземплярів похідних класів

Після того, як посиланню на базовий клас присвоєно значення одного з екземплярів класу з ієрархії, можна спробувати використовувати елементи цього екземпляру (викликати методи, властивості, тощо). У цьому випадку доречним є правило 2: якщо посилання на базовий клас отримує значення об’єкту (екземпляру) похідного класу, то доступ за цим посиланням є тільки до елементів базового класу. Рисунок 3 демонструє використання правила 2.

C#. Спадковість. Демонстрація доступу до елементів класів з допомогою посилання на базовий клас

Рисунок 3. Демонстрація доступу до елементів класів A, B з допомогою посилання rA на базовий клас A

Як видно з рисунку 2, з допомогою посилання на базовий клас можна доступитись до елементів базового класу A. До елементів успадкованого класу B немає доступу. Щоб організувати доступ до елементів успадкованого класу B потрібно використовувати способи приведення типу A до типу B (дивіться пункт 5).



 

4. Приклад, що демонструє обмеження, які можуть виникнути при використанні посилання на базовий клас

У прикладі продемонстровано обмеження доступу до елементів екземпляру objB похідного класу B з посилання rA на базовий клас A. Неможливо викликати елементи класу B без явного приведення типу та використання операторів is, as.

using System;
using static System.Console;

namespace C_sharp
{
  // Клас A - базовий клас
  class A
  {
    public void Show()
    {
      WriteLine("Method A.Show()");
    }

    public void ShowA()
    {
      WriteLine("Method A.ShowA()");
    }
  }

  // Клас B - успадкований клас від класу A
  class B : A
  {
    public void Show()
    {
      WriteLine("Method B.Show()");
    }

    public void ShowB()
    {
      WriteLine("Method B.ShowB()");
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Посилання на базовий клас
      A rA;

      // 2. Екземпляр класу A
      A objA = new A();

      // 3. Екземпляр класу B
      B objB = new B();

      // 4. Посиланню базового класу можна присвоювати
      // значення посилання базового класу - це зрозуміло
      rA = objA;

      // 5. Використання елементів за посиланням
      rA.Show(); // викликається A.Show()
      rA.ShowA(); // A.ShowA()
      // rA.ShowB(); // - помилка, немає доступу до ShowB()

      // 6. Посиланню базового класу можна присвоювати
      // значення посилання похідного класу (правило 1)
      rA = objB; // rA посилається на екземпляр objB класу B
      rA.Show(); // знову викликається A.Show() - важливо
      rA.ShowA(); // A.ShowA()
      // rA.ShowB(); // помилка, знову немає доступу до ShowB()

      // щоб викликати B.Show() потрібно здійснити приведення
      // посилання rA до типу B явним чином.
    }
  }
}

Результат виконання програми

Method A.Show()
Method A.ShowA()
Method A.Show()
Method A.ShowA()

 

5. Способи організації доступу до елементів похідного класу з допомогою посилання на базовий клас. Ключові слова is, as

Як було визначено у попередньому пункті, якщо посилання на базовий клас посилається на екземпляр похідного класу, то з допомогою цього посилання існує доступ тільки до елементів базового класу. Однак, це правило можна змінити і отримати доступ до елементів похідних класів.

Щоб з допомогою посилання на базовий клас отримати доступ елементу похідного класу, потрібно використати один з трьох можливих способів.

  • використати явне приведення до типу успадкованого класу;
  • використати ключове слово as, яке здійснює спробу приведення одного типу до іншого;
  • використати ключове слово as у поєднанні з перевіркою на сумісність типів. Перевірка на сумісність використовує ключове слово is.

На рисунку 4 зображено усі 3 способи для заданих класів A, B які утворюють ієрархію.

C#. Спадковість. Доступ до елементів похідного класу з допомогою посилання на базовий клас

Рисунок 4. Доступ до елементів похідного класу з допомогою посилання на базовий клас

 

6. Приклад, що демонструє способи організації доступу за посиланням до елементів похідного класу. Статичний поліморфізм

У прикладі демонструється 3 способи організації доступу до методу Show() похідного класу B з посилання на базовий клас A. Реалізовані способи демонструють статичний поліморфізм, коли централізований виклик методу формується на етапі компіляції (під час приведення типу).

using System;
using static System.Console;

namespace C_sharp
{
  // Клас A - базовий клас
  class A
  {
    public void Show()
    {
      WriteLine("Method A.Show()");
    }

    public void ShowA()
    {
      WriteLine("Method A.ShowA()");
    }
  }

  // Клас B - успадкований від класу A
  class B : A
  {
    public new void Show()
    {
      WriteLine("Method B.Show()");
    }

    public void ShowB()
    {
      WriteLine("Method B.ShowB()");
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Посилання на базовий клас
      A rA;

      // 2. Екземпляр класу A
      A objA = new A();

      // 3. Екземпляр класу B
      B objB = new B();

      // 4. Доступ до екземпляру базового класу A
      rA = objA;
      rA.Show(); // викликається A.Show()
      rA.ShowA(); // A.ShowA()
      // rA.ShowB(); - помилка, немає доступу

      // 5. Доступ до елементів екземпляру objB
      // з допомогою посилання на A
      rA = objB; // rA посилається на objB

      // 5.1. Спосіб №1. Приведення до типу B - необхідно,
      // щоб виклик rA.Show() => objB.Show().
      try
      {
        // rA привести до типу B
        ((B)rA).Show(); // викликається B.Show()
      }
      catch
      {
        // Якщо приведення rA до типу B не відбулось, то вихід
        WriteLine("Error.");
        return;
      }

      // 5.2. Спосіб №2. Використання ключового слова as.
      // Ключове слово as використовується у випадках,
      // коли потрібно здійснити спробу приведення
      // одного типу до іншого.
      rA = objB;
      if ((rA as B) != null)
        (rA as B).Show(); // B.Show()

      // 5.3. Спосіб №3. Використання поєднання ключових слів is, as.
      // Ключове слово is використовується для визначення
      // сумісності двох типів. Якщо типи сумісні, то результат
      // рівний true, інакше false.
      if (rA is B)
        (rA as B).Show(); // B.Show()
    }
  }
}

 


Зв’язані теми