C#. Урок 9. Наследование

Уроки для опытных   13 марта 2013  Автор статьи:  

Рассмотрим основные принципы наследование классов в C#.

Вспомним из предыдущей статьи синтаксис класса:

[атрибуты]
[модификаторы] class Имя_класса : [родитель]
{
}

Под родителем понимается класс, от которого наследуется данный. Существует несколько понятий, имеющих одно и то же значение, обозначающие наследуемый класс — базовый класс (base class) , родительский класс (parent class), предок. Класс, который наследует, называется производным, потомком или наследником. Потомок наследует все поля, свойства, методы, индексаторы, операторы от предка, помеченные соответствующим модификатором доступа. Кроме этого он может иметь собственные элементы или переопределить существующие.
Наследование можно рассмотреть на примере класса Point2D и класса Point3D, который от него наследуется.

class Point2D
{
protected double x; // поле доступно только в производных классах
protected double y; // поле доступно только в производных классах
public Point2D(double x, double y)
{
this.x = x;
this.y = y;
}
protected Point2D()
:this(0,0)
{ }
}

class Point3D : Point2D
{
private double z;
Point3D(double x, double y, double z)
:base(x,y)
{
this.z = z;
}
}

В данном случае класс Point3D наследует переменные x, y, а также конструктор базового класса. Параметр base действует аналогично this, только используется он всегда для доступа к членам класса-предка, в то время как this — ссылается на текущий экземпляр класса. В этом случае часть объекта, соответствующая базовому классу, создается через вызов его конструктора. А часть, соответствующая производному, — с помощью конструктора потомка. Через параметр base можно вызвать любой конструктор базового класса с соответствующими параметрами.
Добавим по методу GetRadius() в оба класса:

// в Point2D
public double GetRadius()
{
return Math.Sqrt(x * x + y * y);
}
// в Point3D
public new double GetRadius()
{
return Math.Sqrt(x * x + y * y + z * z);
}

Это называется перекрытием метода, а точнее скрытием. В данном случае модификатор new явно скрывает базовый метод GetRadius() и заменяет его методом в производном классе.
Класс, помеченный модификатором sealed не может быть унаследован.

  • 0. В «синтаксисе класса» навскидку пропущено два пункта. Если пропустили сознательно — почему бы не написать «в упрощенном синтаксисе класса» или что-то вроде этого?

    1. В предыдущей статье ошибка — у класса может быть только один родитель.

    2. Зачем?
    protected Point2D()
    :this(0,0)
    { }

    3. protected double x; // поле доступно только в производных классах
    В комментарии оговорка, еще и в объекте этого класса.

    4. В данном случае класс Point3D наследует переменные x, y, а также конструктор базового класса
    Point3D наследует конструктор базового класса? Почему же пример ниже не работает? 🙂
    Point3D point = new Point3D (3, 4);

    5. Последний пример (с сокрытием метода) явно вредный. Люди потом удивляются, почему же код вроде этого работает через ..опу?

    Point2D point = new Point3D(3, 4, 5);
    Console.WriteLine(point.GetRadius);

    6. Про всякие «оговорки» вроде «this ссылается на этот класс» (к которым придираются на собеседованиях/экзаменах) даже говорить не буду.

    • Вот честное слово, так люблю читать твои комментарии. Они всегда конструктивные. Автор статьи в ближайшее время ответит на них.

    • alexxx16

      0. Как угодно, «упрощенный синтаксис». Тут цель — просто показать запись класса-предка в объявлении.
      1. Конечно, исправил.
      2. Если честно, не понял вопроса. Не нравится, что нулевые значения передаются?
      3. Согласен.
      4. Я фигню написал.) Конструкторы классов наследников вызывают конструкторы класса-предка, например, непараметризованный конструктрор Point3D() будет вызывать Point2D(). Мы можем только явно указать, какой из конструкторов будет вызываться.
      5. Ну я не написал, что это приветствуется. Просто надо знать, что такая вещь есть.
      6. Ссылается на текущий экземпляр класса.

  • Гость

    Спасибо Вам за обучающую информацию. Очень много полезного для начинающих. Есть пара вопросов:
    1. Будет ли продолжение статей по С#?
    2. Есть ли у Вас какой-нибудь сборник задач по программированию? Для разных уровней мастерства)
    А в остальном еще раз спасибо за сайт)

Научиться программировать

  • на Delphi

  • на Java

  • на C++