Второй принцип: поддержка наследования в C#
Второй принцип: поддержка наследования в C#
Теперь, после исследования различных подходов, позволяющих создавать классы с хорошей инкапсуляцией, пришло время заняться построением семейств связанных классов. Как уже упоминалось, наследование является принципом ООП, упрощающим многократное использование программного кода. Наследование бывает двух видов: классическое наследование (отношение подчиненности, "is-a") и модель локализации/делегирования (отношение локализации, "has-a"). Сначала мы рассмотрим классическую модель отношения подчиненности.
При создании отношения подчиненности между классами вы строите зависимость между типами. Основной идеей классического наследования является то, что новые классы могут использовать (и, возможно, расширять) функциональные возможности исходных классов. Для примера предположим, что вы хотите использовать функциональные возможности класса Employee и создать два новых класса – Salesperson (продавец) и Manager (менеджер). Иерархия классов будет выглядеть примерно так, как показано на рис. 4.7.
Рис. 4.7. Иерархия классов служащих
Из рис. 4.7 можно понять, что Salesperson (продавец) является ("is-a") Employee (работником), точно так же, как и Manager (менеджер). В классической модели наследования базовые классы (например. Employee) используются для определения общих характеристик, которые будут присущи всем потомкам. Подклассы (например, SalesPerson и Manager) расширяют общие функциональные возможности, добавляя специфические элементы поведения.
Для нашего примера мы предположим, что класс Manager расширяет Employee, обеспечивал запись числа опционов, а класс SalesPerson поддерживает информацию о числе продаж. В C# расширение класса задается в определении класса операцией, обозначаемой двоеточием (:). Так получаются производные типы класса в следующем фрагменте программного кода.
// Добавление двух подклассов в пространстве имен Employees.
namespace Employees {
public class Manager: Employee {
// Менеджер должен знать число опционов.
private ulong numberOfOptions;
public ulong NumbOpts {
get {return numberOfOptions;}
set {numberOfOptions = value;}
}
}
public class SalesPerson: Employee {
// Продавец должен знать число продаж.
private int numberOfSales;
public int NumbSales {
get {return numberOfSales;}
set {numberOfSales = value;}
}
}
}
Теперь, когда создано отношение подчиненности, SalesPerson и Manager автоматически наследуют все открытие (и защищенные) члены базового класса Employee. Например:
// Создание подкласса и доступ к функциональным возможностям
// базового класса.
static void Main (string[] args) {
// Создание экземпляра SalesPerson.
SalesPerson stan = new SalesPerson();
// Эти члены наследуют возможности базового класса Employee.
stan.ID = 100;
stan.Name = "Stan";
// Это определено классом SalesPerson.
stan.NumbSales = 42;
Console.ReadLine();
}
Следует знать, что наследование сохраняет инкапсуляцию. Поэтому производный класс не может иметь непосредственный доступ к приватным членам, определенным базовым классом.