- •Глава 10, описывающая классы как контейнеры их статических членов,
- •Глава 13 посвящена отношениям между классами (и их объектами). Особое
- •Глава 18 включена в книгу при подготовке второго издания. Она посвящен
- •Глава 1. Объектная ориентация программ
- •1.1. Типы, классы, объекты
- •1.2. Программа на c#
- •1.3. Пространство имен
- •1.4. Создание консольного приложения
- •Глава 2. Типы в языке c#
- •2.1. Типы ссылок и типы значений
- •2.2. Классификация типов c#
- •2.3. Простые типы. Константы-литерал
- •2.4. Объявления переменных и констант базовых типо
- •If implicit in int interface
- •Internal is lock long namespace
- •Volatile while
- •Глава 3. Операции и целочисленные выражения
- •3.1. Операции языка c#
- •3.2. Операции присваивания и оператор
- •3.4. Выражения с арифметическими операциями
- •3.6. Переполнения при операциях с целыми
- •Глава 4. Выражения с операндами базовых
- •4.1. Автоматическое и явное приведение арифметических типов
- •4.2. Особые ситуации в арифметических выражениях
- •4.3. Логический тип и логические выражения
- •4.4. Выражения с символьными операндами
- •4.5. Тернарная (условная) операция
- •Глава 5. Типы с# как классы платформы .Net
- •5.1. Платформа .Net Framework и спецификация cts
- •5.2. Простые (базовые) типы c# как классы
- •5.3. Специфические методы и поля простых типов
- •Глава 6. Операторы
- •6.1. Общие сведения об операторах
- •6.2. Метки и оператор безусловного перехода
- •6.3. Условный оператор (ветвлений)
- •If (логическое выражение) оператор_1
- •6.4. Операторы цикла
- •6.5. Операторы передачи управления
- •If (условие) break;
- •6.6. Переключатель
- •Int ball; // оценка в баллах:
- •Глава 7. Массивы
- •7.1. Одномерные массивы
- •Int [ ] integers
- •Int number;
- •7.2. Массивы как наследники класса Array
- •7.3. Виды массивов и массивы многомерные
- •Int [,] dots;
- •Int size;
- •7.4. Массивы массивов и непрямоугольные массивы
- •Int size;
- •7.5. Массивы массивов и поверхностное копирование
- •Int size;
- •Int size;
- •Глава 8. Строки – объекты класса string
- •8.1. Строковые литералы
- •8.2. Строковые объекты и ссылки типа string
- •242.ToString()
- •8.3. Операции над строками
- •8.4. Некоторые методы и свойства класса String
- •8.5. Форматирование строк
- •8.6. Строка как контейне
- •8.7. Применение строк в переключателях
- •8.8. Массивы строк
- •8.8. Сравнение строк
- •Int static Compare (string, string)
- •Int static Compare (string, string, Boolean,CultureInfo)
- •If (string.Compare(res, hen, true,
- •8.9. Преобразования с участием строкового типа
- •38 Попугаев.
- •8.10. Аргументы метода Main( )
- •8.11. Неизменяемость объектов класса String
- •Глава 9. Методы c#
- •9.1. Методы–процедуры и методы-функции
- •9.2. Соотношение фиксированных параметров и аргументов
- •Int iPart;
- •9.3. Параметры с типами ссылок
- •Int[ ] temp;
- •Int[ ] temp;
- •9.4. Методы с переменным числом аргументов
- •VarParams(a, b, c);
- •9.5. Перегрузка методов
- •9.6. Рекурсивные методы
- •4*Fact (3); {
- •9.7. Применение метода Array.Sort()
- •Int имя_функции(тип параметр_1, тип параметр_2)
- •If(условие 2) return -1; // порядок соблюдён
- •Глава 10. Класс как совокупность статических
- •10.1. Статические члены класса
- •10.2. Поля классов (статические поля)
- •Int X; // поле объектов класса
- •10.3. Статические константы
- •10.4. Статические методы
- •10.5. Статический конструктор
- •10.6. Статические классы
- •Глава 11. Классы как типы
- •11.1. Объявление класса
- •11.2. Поля объектов
- •11.3. Объявления методов объектов
- •11.4. Пример класса и его объектов
- •Int count; // текущее показание
- •1 ' Counter.Count' is inaccessible due to its protection leve
- •11.5. Ссылка this
- •Int numb;
- •11.6. Конструкторы объектов класса
- •Int p; // порядок - инициализация по умолчанию
- •Void reduce() // Приведение числа к каноническому виду.
- •11.7. Деструкторы и финализаторы
- •Глава 12. Средства взаимодействия с объектами
- •12.1. Принцип инкапсуляции и методы объектов
- •12.2. Свойства классов
- •Internal, private, static, virtual, sealed, override, abstract, extern
- •Internal protected
- •Int p; // инициализация по умолчанию
- •Void reduce() // "Внутренний" для класса метод
- •12.3. Автореализуемые свойств
- •12.4. Индексаторы
- •Int[] days; // часы по дням недели
- •Int search(string str) { // поиск слова
- •12.5. Индексаторы, имитирующие наличие контейнера
- •Глава 13. Включение, вложение и наследование
- •13.1. Включение объектов классов
- •13.2. Вложение классов
- •13.3. Наследование классов
- •13.4. Доступность членов класса при наследовании
- •13.5. Методы при наследовании
- •13.6. Абстрактные методы и абстрактные классы
- •13.7. Опечатанные классы и методы
- •13.8. Применение абстрактых классов
- •Глава 14. Интерфейсы
- •14.1. Два вида наследования в ооп
- •14.2. Объявления интерфейсов
- •Interface имя_интерфейса
- •Interface iPublication { // интерфейс публикаций
- •Void write(); // готовить публикацию
- •Void read(); // читать публикацию
- •14.3. Реализация интерфейсов
- •Interface iPublication { // интерфейс публикаций
- •Void write(); // готовить публикацию
- •Void read(); // читать публикацию
- •Interface iSeries {
- •Void setBegin(); // восстановить начальное состояние
- •Int GetNext { get; } // вернуть очередной член ряда
- •Int this[int k] {get;} // вернуть к-й член ряда
- •Interface iSeries // интерфейс числовых рядов
- •14.4. Интерфейс как ти
- •Interface iGeo { // интерфейс геометрической фигуры
- •Void transform(double coef); // преобразовать размеры
- •Void display(); // вывести характеристики
- •Interface iGeo {
- •Void transform(double coef); // преобразовать размеры
- •Void display(); // вывести характеристики
- •Ira.Transform(3);
- •Ira.Transform(3);
- •14.5. Интерфейсы и наследование
- •Interface iPublication // интерфейс публикаций
- •Interface iBase
- •Interface iBase {
- •Глава 15. Перечисления и структуры
- •15.1. Перечисления
- •15.2. Базовый класс перечислений
- •IsDe fined"
- •15.3. Структуры
- •15.4. Упаковка и распаковка
- •If (obj is Struct1)
- •If (ob is PointS)
- •If (ob is Double)
- •15.5. Реализация структурами интерфейсов
- •Interface iShape {
- •Interface iShape
- •Information(ci);
- •Information(sp);
- •Interface iImage {
- •Void display();
- •Interface iImage
- •Void display();
- •Глава 16. Исключения
- •16.1. О механизме исключений
- •16.3. Свойства исключений
- •16.4. Управление программой с помощью исключений
- •X; // Вводимое число.
- •16.5. Исключения в арифметических выражениях
- •16.6. Генерация исключений
- •If (!double.TryParse(input, out u))
- •If (!double.TryParse(input, out u)
- •16.7. Пользовательские классы исключений
- •Глава 17. Делегаты и события
- •17.1. Синтаксис делегатов
- •17.2. Массивы делегатов
- •Int X, y; // положение робота на плоскости
- •17.3. Многоадресные (групповые) экземпляры делегатов
- •Virtual
- •17.4. Делегаты и обратные вызовы
- •17.5. Анонимные методы
- •17.6. События
- •Int size; // размер массива
- •Int[ ] ar; // ссылка на массив
- •Int temp;
- •Глава 18. Обобщения
- •18.1. Обобщения как средство абстракции
- •18.2. Декларации обобщённых классов "декларация
- •18.3. Ограничения типизирующих параметров
- •Intemface iComparable {
- •Int CompareTo (object p);
- •18.4. Обобщённые структуры "обобщённые структуры"
- •18.5. Обобщённые интерфейсы "обобщённый интерфейс"
- •Int add(t X, t y); // прототип метода
- •18.6. Обобщённые методы "обобщённые методы"
- •18.7. Обобщённые делегаты "обобщённые делегаты"
- •Virtual
- •InnerException
- •Interface
13.4. Доступность членов класса при наследовании
Члены базового класса, имеющие статус доступа private как были недоступны
для внешнего по отношению к объявлению базового класса мира, так и остаются
закрытыми
для
базового
класса.
Члены
производного
класса,
имеющие
модификатор public, открыты для членов и объектов производного класса.
В ряде случаев необходимо, чтобы члены базового класса были доступны
(открыты) для членов производного класса, но в то же время были закрыты
(недоступны) для объектов производного класса. В этом случае в базовом классе
эти члены "защищённые члены" должны быть защищенными, то есть объявлены
с модификатором protected
"модификатор: protected" . Сразу же отметим, что
если класс рассматривается вне наследования, то защищенные члены ничем не
отличаются от закрытых. К защищенным членам класса нельзя обращаться извне
объявления класса.
В производном классе обычно вводятся новые члены, определяющие новое
поведение и дополнительные характеристики объектов производного класса. Для
новых (не унаследованных) членов производных классов имена выбираются
произвольно.
Если в производном классе объявлен член, имя которого совпадает с именем
какого-либо члена базового класса, то для их различения в производном классе
используются уточненные имена:
this.имя_члена_производного_класса
base.имя_члена_базового_класс
а
При внешних обращениях одноименные члены базового и производного класса
различаются по типам объектов, для которых эти обращения выполнены.
Рассмотрим пример. Определим класс "круг" и производный от него класс
"кольцо". Предположим, что у нас нет необходимости создавать объекты класса
"круг", и он будет использоваться только как базовый для определения других
классов. Тогда его определение может быть таким (Программа 13_05.cs):
class Disk // класс круг
{
protected double rad; // радиус круга
protected Disk(double ri) { rad = ri; } // конструктор
protected double Area { get { return rad * rad * Math.PI; } }
}
В классе Disk одно поле rad, задающее значение радиуса круга, конструктор
общего вида и свойство Area, позволяющее получить значение площади круга.
Параметр конструктора явно использован в теле конструктора, где он задает
значение поля rad, то есть определяет радиус круга. Все члены класса объявлены с
модификатором protected. При таком определении класс вне наследования ни к
чему не годен. Невозможно создать объект класса Disk – его конструктор
защищённый (protected). Если убрать явно определенный конструктор, компилятор
добавит открытый конструктор умолчания. Но и в этом случае пользы не видно –
создав объект, нельзя будет обратиться к его полю или свойству.
Используем класс Disk в качестве базового в следующем объявлении:
class Ring : Disk // класс кольцо
{
new double rad; // радиус внутренней окружности
// конструктор:
public Ring(double Ri, double ri)
: base(Ri) { rad = ri; }
public new double Area
{ get { return base.Area - Math.PI * rad * rad; } }
public void print()
{
Console.WriteLine("Ring: Max_radius={0:f2}, " +
"Min_radius={1:f2}, Area={2:f3}",
base.rad, rad, Area);
}
}
В производном классе Ring поле new double rad определяет значение
внутренней окружности границы кольца. Радиус внешней границы определяет
одноимённое поле double rad, унаследованное из базового класса. Оба поля вне
объявления класса Ring недоступны. Конструктор производного класса Ring
объявлен явно, как открытый метод класса. У этого конструктора два параметра,
позволяющие задавать значения радиусов границы кольца. В теле конструктора
второй параметр double ri определяет внутренний радиус. В инициализаторе
конструктора :base(Ri) выполнено явное обращение к конструктору базового класса
Disk. Параметр конструктора Ri служит аргументом в этом обращении. Отметим,
что для простоты не используются никакие проверки допустимости значений
параметров.
Обратите внимание, что в объявление поля rad производного класса Ring
входит модификатор new
"модификатор: new" . Появление new обусловлено
следующим соглашением языка C#. Имя члена производного класса может
совпадать (вольно или по ошибке) с именем какого-либо члена базового класса. В
этом случае имя члена производного класса скрывает или, говорят, экранирует
"экранирование"
соответствующее имя члена базового класса. При отсутствии
модификатора new компилятор выдаёт сообщение с указанием совпадающих имён и
предложением "Use the new keyword if hiding was intended" – "Используйте
служебное слово new, если экранирование запланировано". Именно для того, чтобы
удостоверить компилятор в преднамеренном совпадении имён радиус внутренней
окружности объявлен с модификатором new. То же самое сделано и при
объявлении в классе Ring свойства Area, позволяющего получить площадь кольца.
Кроме того, класс Ring унаследовал свойство с тем же именем из базового класса. В
get-аксессоре свойства Area из класса Ring выполнено явное обращение base.Area к
свойству базового класса Disk. Открытый метод print() позволяет вывести сведения
об объекте класса Ring. Они выводятся как значения полей base.rad, rad и свойств
а
Area. Отметим, что принадлежность членов rad и Area классу Ring можно
подчеркнуть, если задать аргументы метода WriteLine() в таком виде:
Console.WriteLine("Ring: Max_radius={0:f2}, " + "Min_radius={1:f2},
Area={2:f3}",
base.rad, this.rad, this.Area);
В качестве иллюстрации возможностей класса Ring рассмотрим такой
фрагмент программы:
class Program {
static void Main() {
Ring rim = new Ring(10.0, 4.0);
rim.print();
}
}
Результат выполнения программы:
Ring: Max_radius=10,00, Min_radius=4,00, Area=263,894
Для иллюстрации доступности членов классов при наследовании удобно
использовать схему, приведённую на рис. 13.5. Так как при изложении материала
мы не затронули понятие сборки, то члены с модификатором internal на схеме не
показаны. Стрелки на схеме обозначают возможность обращения (доступность) к
членам с разными модификаторами.
Рис. 13.5. Доступность членов при наследовании классов
Если класс В является наследником (производным от) класса А, то для
объекта класса В (objectB на рис. 13.5) доступны открытые члены классов А и В. В
то же время для членов производного класса В доступны открытые и защищённые
члены класса А (само собой доступны и все члены самого класса В). Объект класса
А (objectА на схеме) никогда не имеет доступа к членам производного класса В.
