C#. Доступ к элементам базового класса из унаследованного класса. Ключевые слова base, new. Примеры

Доступ к элементам базового класса из унаследованного класса. Ключевые слова base, new. Примеры


Содержание


1. Ключевое слово base. Назначение. В каких случаях используется ключевое слово base?

Ключевое слово base есть актуальным в случаях, когда между классами используется отношение наследования. Здесь возможна ситуация, что в базовом и унаследованном классах существуют методы (элементы) с одинаковыми именами и сигнатурами. В этом случае элемент в производном классе скрывает (переопределяет) соответствующий элемент базового класса. Чтобы из унаследованного класса получить доступ к элементу базового класса нужно использовать ключевое слово base.

Ключевое слово base используется в унаследованных классах в следующих случаях:

  • когда из конструктора производного класса нужно вызвать конструктор базового класса. Более подробно об этом способе использования base описывается здесь;
  • когда из метода производного класса нужно вызвать метод базового класса, если этот метод переопределяется;
  • когда из метода производного класса нужно получить доступ к члену данных базового класса. В этом случае член данных может быть объявлен с любым модификатором доступа кроме private;
  • когда из метода производного класса нужно получить доступ к свойству базового класса (свойство не объявлено как private);
  • если нужно подчеркнуть (конкретизировать), что в данном методе унаследованного класса используются элементы базового класса.

 

2. Вызов методов базового класса с помощью base. Общая форма. Пример

С помощью ключевого слова base можно обращаться к любым элементам базового класса, которые не являются скрытыми (не содержат модификатора private).

Общая форма использования ключевого слова base для доступа к методу базового класса следующая:

base.Method();

где Method() – метод базового класса. Если в производном классе нет реализации метода с именем Method(), то использование base необязательно.

Общая форма использования ключевого слова base для доступа к члену данных (не private члену данных)

base.variable;

где variable – имя члена данных базового класса.

 

3. Графическое объяснение доступа к элементам с помощью ключевого слова base

На рисунке 1 демонстрируется доступ к элементам базового класса A из метода производного класса B.

C#. Наследование. Ключевое слово base. Способы доступа к разным элементам классов

Рисунок 1. Способы доступа к разным элементам классов A, B из метода Method()

 



4. Пример, который демонстрирует использования ключевого слова base для доступа к различным элементам базового класса

Пусть заданы два класса A и B. Базовый класс A содержит следующие элементы:

  • внутреннее поле d с модификатором доступа protected;
  • внутреннее поле a с модификатором доступа private;
  • public-метод с именем Method1();
  • public-свойство AA, которое реализует доступ к внутреннему полю a.

Класс B наследует класс A и содержит следующие элементы:

  • внутреннее поле d с модификатором доступа protected;
  • внутреннее поле b с модификатором доступа private;
  • public-метод с именем Method1();
  • public-свойство BB, реализующее доступ к внутреннему полю b.

Демонстрационный текст программы, созданной по шаблону Console Application следующий

using static System.Console;

namespace C_sharp
{
  // Класс A - базовый для класса B
  class A
  {
    // 1. Внутренние поля класса
    protected int d;
    private int a;

    // 2. Конструктор класса
    public A()
    {
      // инициализирует поля некоторыми значениями
      a = 10;
      d = 20;
    }

    // 3. Общедоступный метод класса
    public void Method1()
    {
      WriteLine("A.Method1()");
    }

    // 4. Общедоступное свойство - доступ к полю a
    public int AA
    {
      get { return a; }
      set { a = value; }
    }
  }

  // Класс B - унаследованный от класса A
  class B : A
  {
    // 1. Внутренние поля класса
    // Поле d перекрывает одноименное поле d класса A,
    protected int d;
    private int b;

    // 2. Конструктор класса
    public B()
    {
      d = 40;
      b = 50;
    }

    // 2. Метод, который перекрывает метод Method1() класса A,
    // в этом методе демонстрируется доступ
    // к разным элементам класса A
    public void Method1()
    {
      WriteLine("B.Method1()");

      // 1. Обращение к методу Method1() класса A
base.Method1();

      // 2. Вызов свойства AA класса A
      int t = AA; // здесь можно без слова base
      WriteLine("A.AA = {0}", t);

      // 3. Доступ к внутреннему полю d класса A
      t = base.d; // поле d класса A
      WriteLine("A.t = {0}", t);

      // 4. Доступ к полю a класса A - запрещено
      // t = base.a; // запрещено, поле A.a есть private
    }

    // 3. Общедоступное свойство BB
    public int BB
    {
      get { return b; }
      set { b = value; }
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Демонстрация использования ключевого слова base
      // 1. Создать экземпляр класса B
      B obj = new B();

      // 2. Вызвать метод Method1 класса B,
      // в этом методе используются элементы класса A
      objB.Method1();
    }
  }
}

 

5. Доступ к свойствам базового класса с помощью base. Пример базового класса Circle и производного класса Sector

В примере демонстрируется доступ к свойству базового класса. Заданы два класса: Circle – базовый класс, Sector – унаследованный класс от Circle. В обоих классах есть свойство Area. Чтобы из производного класса Sector вызвать свойство Area базового класса нужно обратиться следующим образом

base.Area;

Ниже приведен текст программы, которая демонстрирует применение ключевого слова base.

using System;
using static System.Console;

namespace C_sharp
{
  // Класс Circle - окружность
  class Circle
  {
    // 1. Внутренние поля
    protected double radius; // радиус
    protected double x, y; // координаты центра кола

    // 2. Конструктор
    public Circle(double _x, double _y, double _radius)
    {
      x = _x;
      y = _y;
      if (_radius <= 0)
        radius = 1.0;
      else
        radius = _radius;
    }

    // 3. Свойства - доступ к внутренним полям класса
    public double X
    {
      get { return x; }
      set { x = value; }
    }

    public double Y
    {
      get { return y; }
      set { y = value; }
    }

    public double Radius
    {
      get { return radius; }
      set
      {
        if (value <= 0)
          radius = 1.0;
        else
          radius = value;
      }
    }

    // 4. Свойство Area - возвращает площадь окружности
    public double Area
    {
      get { return Math.PI * radius * radius; }
    }
  }

  // Класс Sector - сектор (часть окружности)
  class Sector : Circle
  {
    // 1. Внутреннее поле
    protected double alpha; // угол сектора alpha = 0..360

    // 2. Конструктор – вызывает конструктор базового класса Circle
    public Sector(double _x, double _y, double _radius, double _alpha) :
                base(_x, _y, _radius)
    {
      if ((_alpha >= 0) && (_alpha < 360))
        alpha = _alpha;
      else
        alpha = 0.0;
    }

    // 3. Свойство для доступа к внутреннему полю
    public double Alpha
    {
      get { return alpha; }
      set
      {
        if ((value >= 0) && (value < 360))
          alpha = value;
        else
          alpha = 0.0;
      }
    }

    // 4. Свойство, которое вычисляет площадь     сектора
    // вызывает одноименное свойство базового класса
    public double Area
    {
      get
      {
        // Вызвать свойство базового класса
        return base.Area * alpha / 360;
      }
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      Sector sc = new Sector(1.5, 2.2, 3.0, 100);
      double x = sc.Area;

      // вывести площадь сектора
      WriteLine("Area of sector = {0:f3}", x);
    }
  }
}

Как видно из вышеприведенного кода, в базовом классе Circle реализовано свойство Area, которое используется в одноименном свойстве производного класса Sector следующим образом

...

class Sector
{
  ...

  // 4. Свойство, вычисляющее площадь сектора,
  // вызывает одноименное свойство базового класса
  public double Area
  {
    get
    {
      // Вызвать свойство базового класса
      return base.Area * alpha / 360;
    }
  }
}

...

 

6. Необходимость применения ключевого слова new

Ключевое слово new может быть применено в унаследованном классе перед именем элемента, который перекрывает (скрывает) имя базового класса. Использование слова new рекомендуется компилятором в случае, когда нужно подчеркнуть, что именно данный метод или свойство переопределяют одноименный метод базового класса.
На рисунке 2 обозначено использование слова new для переопределения метода в производном классе.

C#. Наследование. Ключевое слово new при наследовании

Рисунок 2. Способы реализации метода Method(), который переопределяет одноименный метод базового класса

Если не указывать ключевое слово new в методе унаследованного класса, то это не повлияет на функциональность программы. Однако, в этом случае компилятор будет выдавать предупреждение:

B.Method hides inherited member A.Method. Use the new keywork if hiding was intended

Кроме того, компилятор предложит исправить эту неточность и, если нужно, сам установит ключевое слово new в нужном месте.

 


Связанные темы