Чтение онлайн

ЖАНРЫ

ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Троелсен Эндрю

Шрифт:

// базового класса.

static void Main (string[] args) {

 // Создание экземпляра SalesPerson.

 SalesPerson stan = new SalesPerson;

 // Эти члены наследуют возможности базового класса Employee.

 stan.ID = 100;

 stan.Name = "Stan";

 // Это определено классом SalesPerson.

 stan.NumbSales = 42;

 Console.ReadLine;

}

Следует

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

Управление созданием базовых классов с помощью base

В настоящий момент SalesPerson и Manager можно создать только с помощью конструктора, заданного по умолчанию. Поэтому предположим, что в тип Manager добавлен новый конструктор с шестью аргументами, который вызывается так, как показано ниже.

static void Main(string[] args) {

 // Предположим, что есть следующий конструктор с параметрами

 // (имя, возраст, ID, плата, SSN, число опционов).

 Manager chucky = new Manager("Chucky", 35, 92, 100000, "333-23-2322", 9000);

}

Если взглянуть на список аргументов, можно сразу понять, что большинство из них должно запоминаться в членах-переменных, определенных базовым классом Employee. Для этого вы могли бы реализовать этот конструктор так, как предлагается ниже.

// Если не указано иное, конструктор подкласса автоматически вызывает

// конструктор базового класса, заданный по умолчанию.

public Manager(string fullName, int age, int empID, float currPay, string ssn, ulong numbOfOpts) {

 // Это наш элемент данных.

 numberOfOptions = numbOfOpts;

 // Использование членов, наследуемых от Employee,

 // для установки данных состояния.

 ID = empID;

 Age = age;

 Name = fullName;

 SocialSecurityNumber = ssn;

 Pay = currPay;

}

Строго говоря, это допустимый, но не оптимальный вариант. В C#, если вы не укажете иное, конструктор базового класса, заданный по умолчанию, вызывается автоматически до выполнения логики любого пользовательского конструктора Manager. После этого текущая реализация получает доступ к множеству открытых свойств базового класса Employee, чтобы задать его состояние. Поэтому здесь при создании производного объекта вы на самом деле "убиваете семь зайцев" (пять наследуемых свойств и два вызова конструктора)!

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

// На этот раз используем ключевое слово C# "base" для вызова

// пользовательского конструктора с базовым классом.

public Manager (string fullName, int age, int empID, float currPay, string ssn, ulong numbOfOpts): base(fullName, age, empID, currPay, ssn) {

 numberOfOptions = numbOfOpts;

}

Здесь

конструктор был дополнен довольно запутанными элементами синтаксиса. Непосредственно после закрывающей скобки списка аргументов конcтруктора стоит двоеточие, за которым следует ключевое слово C# base. В этой ситуации вы явно вызываете конструктор с пятью аргументами, определенный классом Employees избавляясь от ненужных вызовов в процессе создания дочернего класса.

Конструктор SalesPerson выглядит почти идентично.

// Как правило, каждый подкласс должен явно вызывать

// подходящий конструктор базового класса.

public SalesPerson(string fullName, int age, int empID, float currPay, string ssn, int numbOfSales): base(fullName, age, empID, currPay, ssn) {

 numberOfSales = numbOfSales;

}

Вы должны также знать о том. что ключевое слово base можно использовать всегда, когда подклассу нужно обеспечить доступ к открытым или защищенным членам, определённым родительским классом. Использование этого ключевого слова не ограничено логикой конструктора. В нашем следующем обсуждении полиморфизма вы увидите примеры, в которых тоже используется ключевое слово base.

Множественные базовые классы

Говоря о базовых классах, важно не забывать, что в C# каждый класс должен иметь в точности один непосредственный базовый класс. Таким образом, нельзя иметь тип с двумя или большим числом базовых классов (это называется множественным наследованием). Вы увидите в главе 7, что в C# любому типу позволяется иметь любое число дискретных интерфейсов. Таким образом класс в C# может реализовывать различные варианты поведения, избегая проблем, присущих классическому подходу, связанному с множественным наследованием. Аналогично можно сконфигурировать обычный интерфейс, как производный от множественных интерфейсов (см. главу 7).

Хранение семейных тайн: ключевое слово protected

Вы уже знаете, что открытые элементы непосредственно доступны отовсюду, а приватные элементы недоступны для объектов вне класса, определяющего эти элементы. Язык C#, занимающий лидирующие позиции среда многих других современных объектных языков, обеспечивает еще один уровень доступа: защищенный.

Если базовый класс определяет защищенные данные или защищенные члены, он может создать набор элементов, которые будут непосредственно доступны для любого дочернего класса. Например, чтобы позволить дочерним классам SalesPerson и Manager непосредственный доступ к сектору данных, определенному классом Employee, обновите оригинальное определение класса Employee так, как показано ниже.

// Защищенные данные состояния.

public class Employee {

 // Дочерние классы могут иметь непосредственный доступ

 // к этой информации, а пользователи объекта – нет.

 protected string fullName;

 protected int empID;

 protected float currPay;

 protected string empSSN;

Поделиться с друзьями: