Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
26
Добавлен:
29.02.2016
Размер:
69.59 Кб
Скачать

Добавление в иерархию конструктора

Для начала возьмем простейший случай и посмотрим, что произойдет, если где-то в иерар­хии заменить конструктор по умолчанию другим конструктором, не имеющим параметров. Предположим, вы решили, что имя всегда должно быть инициировано строкой "<no name>" вместо ссылки на null. Модифицируем код GenericCustomer следующим образом:

public abstract class GenericCustomer

{

private string name;

public GenericCustomer()

:based //эту строку можно пропустить без влияния

//на скомпилированный код

{

name = "<no name>";

}

}

После добавления этого кода все будет работать хорошо. У Nevermore60Customer по-прежнему имеется конструктор по умолчанию, поэтому описанная ранее последователь­ность событий происходит, как и раньше, за исключением того, что компилятор будет вызывать пользовательский конструктор GenericCustomer вместо конструктора по умол­чанию, поэтому поле name всегда будет инициализировано строкой "<no name>", что и требовалось.

Обратите внимание, что перед запуском вашего конструктора GenericCustomer доба­вился вызов конструктора базового класса с применением синтаксиса, который использо­вался ранее во время обсуждения, как получить различные перегрузки конструкторов для вызова друг друга. Единственное отличие состоит в том, что на этот раз присутствует клю­чевое слово base вместо this, указывающее на то, что вызывается конструктор базового класса, а не другой конструктор этого же класса. В скобках после ключевого слова base не задано никаких параметров; это важно, поскольку означает, что никакие параметры базо­вому конструктору не передаются, поэтому компилятор будет искать для вызова конструк­тор без параметров. В результате всего этого компилятор вставит код вызова конструктора System.Object, что произошло бы по умолчанию в любом случае.

На самом деле, эту строку кода можно опустить и написать следующее (как делалось с множеством конструкторов, рассмотренных до сих пор в этой главе):

public GenericCustomer()

{

name = "<no name>";

}

Если компилятор не обнаруживает никаких ссылок на другой конструктор перед откры­тием "фигурной скобки, то предполагает, что вы намерены вызвать конструктор базового класса; так работает и конструктор по умолчанию.

Ключевые слова base и this  единственные ключевые слова, которые допускаются в' этой строке для вызова другого конструктора. Все остальное приведет к ошибке во время ком­пиляции. Также следует отметить, что может быть указан только один другой конструктор.

До сих пор код работал хорошо. Одним из способов испортить все это путешествие по иерархии конструкторов может быть объявление конструктора с модификатором private:

i

private GenericCustomer() {

name = "<no name>";

Если вы попробуете сделать так, то столкнетесь с интересной ошибкой компиляции, которая может действительно поразить, если вы не понимаете, как вызываются конструк­торы в иерархии классов:

‘Wrox.ProCSharp.GenericCustomer.GenericCustomer()’ is inaccessible due to its protection level

'Wrox.ProCSharp.GenericCustomer.GenericCustomer()' не доступен из-за его уровня защиты

Интересно, что эта ошибка появится не в классе GenericCustomer, а в классе-наслед­нике Nevermore60Customer. А происходит здесь вот что: компилятор пытается сгенери­ровать конструктор по умолчанию для Nevermore60Customer, но не может этого сделать, потому что конструктор по умолчанию должен вызвать конструктор без параметров ба­зового класса GenericCustomer. Объявив этот конструктор как private, вы тем самым сделали его недоступным для классов-наследников. Похожая ошибка случится, если опре­делить конструктор GenericCustomer, принимающий параметры, но не определить кон­структора без параметров. В таком случае компилятор не генерирует конструктор по умол­чанию для GenericCustomer, поэтому, когда он попытается сгенерировать конструктор по умолчанию для любого класса-наследника, он не сможет этого сделать, потому что не найдет конструктора базового класса без параметров. Чтобы обойти это, в производный класс понадобится добавить собственные конструкторы, даже если делать в них ничего не нужно  лишь только для того, чтобы компилятор не пытался генерировать для класса конструктор по умолчанию.

Теперь, обладая необходимыми теоретическими знаниями, вы готовы к изучению при­мера аккуратного добавления конструкторов в иерархию классов. В следующем разделе мы начнем добавлять конструкторы с параметрами в пример программы МогtimeгPhones.

Соседние файлы в папке 04 Наследование