Наследование в Си-шарп. Конструктор базового класса

В этом уроке мы рассмотрим с вами один из базовых принципов объектно-ориентированного программирования – наследование.

Начнем рассмотрение наследования из жизненных ситуаций. Для примера, возьмем такие понятия, как человек и студент. У любого человека есть имя, рост, вес и другие общие характеристики. Студент же является частным случаем человека, у него также есть имя, рост, вес, но кроме этого, он учится в некотором ВУЗе, на определенной специальности и имеет средний балл. С точки зрения наследования, в этом случае, студент является наследником понятия человек. Еще один пример можно привести с животными. Животное - это общее понятие. Животных можно поделить на рыб, птиц и млекопитающих. Каждый из этих групп животных различаются некоторым характеристиками, но у всех них есть общие особенности животных.

А теперь перейдем к программированию

В программировании наследование позволяет создавать новый класс на базе другого. Класс, на базе которого создается новый класс, называется базовым, а базирующийся новый класс – наследником или производным классом. В класс-наследник из базового класса переходят поля, свойства, методы и другие члены класса.

Объявление нового класса, который будет наследовать другой класс, выглядит так:

class [имя_класса] : [имя_базового_класса]
{
// тело класса
}


Приведу простой пример использования наследования. На основе базового класса Животное создаются два класса Собака и Кошка, в эти два класса переходит свойство Имя животного:

class Animal
{
public string Name { get; set; }
}
class Dog : Animal
{
public void Guard()
{
// собака охраняет
}
}
class Cat : Animal
{
public void CatchMouse()
{
// кошка ловит мышь
}
}
class Program
{
static void Main(string[] args)
{
Dog dog1 = new Dog();
dog1.Name = "Барбос"; // называем пса
Cat cat1 = new Cat();
cat1.Name = "Барсик"; // называем кота
dog1.Guard(); // отправляем пса охранять
cat1.CatchMouse(); // отправляем кота на охоту
}
}


Вызов конструктора базового класса в Си-шарп

В базовом классе и классе-наследнике могут быть объявлены конструкторы, и тут возникает вопрос – какой конструктор за что должен отвечать, и как их вызывать. Логично будет сказать то, что конструктор базового класса будет создавать ту часть объекта, которая принадлежит базовому классу (ведь из базового класса о наследнике ничего неизвестно), а конструктор из наследника будет создавать свою часть.

Когда конструктор определен только в наследнике, то здесь всё просто – при создании объекта сначала вызывается конструктор по умолчанию базового класса, а затем конструктор наследника.

Когда конструкторы объявлены и в базовом классе, и в наследнике – нам необходимо вызывать их оба. Для вызова конструктора базового класса используется ключевое слово base. Объявление конструктора класса-наследника с вызовом базового конструктора имеет следующую структуру:

[имя_конструктора_класса-наследника] ([аргументы]) : base ([аргументы])
{
// тело конструктора
}


В базовый конструктор передаются все необходимые аргументы для создания базовой части объекта.

Приведу пример вызова базового конструктора. Есть тот же класс Животное и класс Попугай. В классе Животное есть только свойство Имя, и конструктор, который позволяет установить это имя. В классе Попугай есть свойство Длина клюва и конструктор, в котором мы задаем эту длину. При создании объекта Попугай мы указываем два аргумента – имя и клюв, и дальше аргумент Имяпередается в базовый конструктор, он вызывается, и после его работы выполнение передается конструктору класса Попугай, где устанавливается длина:

class Animal
{
public string Name { get; set; }

public Animal(string name)
{
Name = name;
}
}
class Parrot : Animal
{
public double BeakLength { get; set; } // длина клюва

public Parrot(string name, double beak) : base(name)
{
BeakLength = beak;
}
}
class Dog : Animal
{
public Dog(string name) : base (name)
{
// здесь может быть логика создания объекта Собака
}
}
class Program
{
static void Main(string[] args)
{
Parrot parrot1 = new Parrot("Кеша", 4.2);
Dog dog1 = new Dog("Барбос");
}
}


Доступ к членам базового класса из класса-наследника

Здесь стоит отметить, что в классе-наследнике мы можем получить доступ к членам базового класса которые объявлены как public, protected, internal и protected internal. Члены базового класса с модификатором доступа privateтакже переходят в класс-наследник, но к ним могут иметь доступ только члены базового класса. Например, свойство, объявленное в базовом классе, которое управляет доступом к закрытому полю, будет работать корректно в классе-наследнике, но отдельно получить доступ к этому полю из класса-наследника мы не сможем.

Домашнее задание

Создайте базовый класс Геометрическая фигура, предусмотрите в нем общие поля/свойства, например координаты центра фигуры, с помощью конструктора должна быть возможность задать центр. На базе этого класса создайте два новых – Треугольник и Окружность. В этих классах должны быть свои особые поля, например радиус для окружности. В оба класса добавьте метод Нарисовать, в котором могла бы быть специфическая логика рисования фигуры. Создайте объекты треугольник и окружность.

PS. Не забываем подписываться на обновления по электронной почте в форме ниже!

Наши рекомендации