
- •Лекции по курсу "Технология программирования" (1-й семестр) Оглавление
- •Технология .Net Предыдущее состояние дел.
- •Главные компоненты платформы .Net (clr, cts и cls)
- •Общеязыковая среда выполнения (clr)
- •О бщая система типов и общеязыковые спецификации (cts и cls)
- •Библиотека базовых классов
- •Роль языка с#
- •Компоновочные блоки
- •Роль метаданных типов .Net
- •Роль манифеста компоновочного блока
- •Общая система типов.
- •Объектно-ориентированное программирование
- •Главные элементы объектно-ориентированного подхода
- •Дополнительные элементы ооп
- •Принципы объектно-ориентированного программирования.
- •Классы Инкапсуляция
- •Объект (экземпляр класса).
- •Ключевое слово this
- •Отношения между объектами.
- •Основные отличительные особенности класса
- •Спецификаторы доступа
- •Состав класса
- •Поля класса
- •Доступ к полям
- •Статические и экземплярные переменные
- •Методы (функции-члены класса)
- •Переменное число параметров метода
- •Статические методы
- •Конструкторы
- •Закрытые конструкторы или классы без экземпляров
- •Статические конструкторы.
- •Деструкторы
- •Абстрактные методы и классы.
- •Свойства
- •Индексаторы
- •Статические классы
- •Частичные классы
- •Рекомендации по программированию
- •Наследование Понятие наследования в программировании
- •Типы наследования
- •Наследование реализации
- •Определение наследующих классов
- •Уровень доступа protected и internal
- •Ссылка на объект базового класса
- •Протоклассы
- •Предотвращение наследования с помощью ключевого слова sealed.
- •Отношения между классами
- •Абстрактные классы.
- •Класс object
- •Функциональные замыкания
- •Разработка функциональных замыканий с помощью наследования
- •Разработка функциональных замыканий с помощью экземпляров класса
- •Заключение.
- •Полиморфизм
- •Полиморфизм наследующих классов.
- •Переопределение методов родительского класса. Раннее связывание.
- •Виртуальные методы и их переопределение.
- •Как вызывают виртуальные методы
- •Виртуальные функции и принцип полиморфизма
- •Перегрузка.
- •Перегруженные конструкторы
- •Рекомендации программисту.
Состав класса
В общем случае класс может содержать следующие функциональные элементы:
Данные: переменные или константы.
Методы, реализующие не только вычисления, но и другие действия, выполняемые классом или его экземпляром.
Конструкторы (реализуют действия по инициализации экземпляров или класса в целом).
Свойства (определяют характеристики класса в соответствии со способами их задания и получения).
Деструкторы (определяют действия, которые необходимо выполнить до того, как объект будет уничтожен).
Индексаторы (обеспечивают возможность доступа к элементам класса по их порядковому номеру).
Операции (задают действия с объектами с помощью знаков операций).
События (определяют уведомления, которые может генерировать класс).
Вложенные типы (типы данных, внутренние по отношению к классу).
Рассмотрим первую категорию элементов класса. Прежде чем приступить к проектированию классов, необходимо поговорить о присваивании и сравнении объектов. Механизм выполнения присваивания один и тот же для величин любого типа, как ссылочного, так и размерного, однако результаты различаются. При присваивании значения копируется значение, а при присваивании ссылки — ссылка, поэтому после присваивания одного объекта другому мы получим две ссылки, указывающие на одну и ту же область памяти:
Пусть были созданы три объекта а, b и с, а затем выполнено присваивание b = с. Теперь ссылки b и с указывают на один и тот же объект. Старое значение b становится недоступным и очищается сборщиком мусора.
Аналогичная ситуация с операцией проверки на равенство. Величины значимого типа равны, если равны их значения. Величины ссылочного типа равны, если они ссылаются на одни и те же данные. Так, объекты b и с равны, т.к. они ссылаются на одну и ту же область памяти. Но а не равно b даже при равенстве их значений.
Поля класса
Поле представляет собой переменную, связанную с данным классом или его экземпляром. Поля класса синтаксически являются обычными переменными (объектами) и их описание удовлетворяет обычным правилам объявления переменных. Содержательно поля задают представление той самой абстракции данных, которую реализует класс. Поля характеризуют состояние объектов класса. Когда создается новый объект класса (в динамической памяти или в стеке), то этот объект представляет собой набор полей класса. Два объекта одного класса имеют один и тот же набор полей, но отличаются значениями, хранимыми в этих полях. Все объекты класса Person могут иметь поле, характеризующее рост персоны, но один объект может быть высокого роста, другой - низкого, а третий - среднего роста.
Язык C# является языком со строгой типизацией. В соответствии с этим в нем определены 7 видов переменных: статические, значащие, экземплярные, элементы массивов, входные параметры, выходные параметры, локальные переменные.
Доступ к полям
Данные, содержащиеся в классе, могут быть переменными или константами. При описании данных также можно указывать атрибуты и спецификаторы, задающие различные
характеристики элементов.
Синтаксис описания элемента данных следующий:
[атрибуты] [спецификаторы] [const] тип имя [ = начальное_значение ]
Возможные значения спецификаторов приведены в следующей таблице:
№ |
Спецификатор |
Описание |
|
public |
Доступ к элементу не ограничен |
|
protected |
Доступ только из данного и производных классов |
|
private |
Доступ только из данного класса |
|
internal |
Доступ только из данной сборки |
|
protected internal |
Доступ только из данного и производных классов и из данной сборки |
|
new |
Новое описание поля, скрывающее унаследованный элемент класса |
|
static |
Одно поле для всех экземпляров класса |
|
readonly |
Поле доступно только для чтения (значение таких полей можно установить либо при описании, либо в конструкторе) |
|
volatile |
Поле может изменяться другим процессом или системой |
Для констант можно использовать только спецификаторы 1-5.
Каждое поле имеет модификатор доступа, принимающий одно из пяти значений: public, private, protected, internal и protected internal. Атрибутом доступа по умолчанию является атрибут private. Для полей класса этот вид доступа является предпочтительным, поскольку поля определяют внутреннее строение класса, которое должно быть скрыто от пользователя. Все методы класса имеют непосредственный доступ к его закрытым полям.
Независимо от значения атрибута доступа, все поля доступны для всех методов класса. Они являются для методов класса глобальной информацией, с которой работают все методы, извлекая из полей нужные им данные и изменяя их значения в ходе работы. Если поля доступны только для методов класса, то они имеют атрибут доступа private, который можно опускать. Такие поля считаются закрытыми, но часто желательно, чтобы некоторые из них были доступны в более широком контексте. Если некоторые поля класса A должны быть доступны для методов класса B, являющегося потомком класса A, то эти поля следует снабдить атрибутом protected. Такие поля называются защищенными. Если некоторые поля должны быть доступны для методов классов B1, B2 и так далее, дружественных по отношению к классу A, то эти поля следует снабдить атрибутом internal, а все дружественные классы B поместить в один проект (assembly). Такие поля называются дружественными. Наконец, если некоторые поля должны быть доступны для методов любого класса B, которому доступен сам класс A, то эти поля следует снабдить атрибутом public. Такие поля называются общедоступными или открытыми.
Поля, описанные со спецификатором static, а также константы существуют в единственном экземпляре для всех объектов класса, поэтому к ним обращаются не через имя экземпляра, а через имя класса. Обращение к полю класса выполняется с помощью операции доступа (точка). Справа от точки задается имя поля, слева — имя экземпляра для обычных полей или имя класса для статических. Рассмотрим пример создания класса Circle и два способа обращения к его полям.
class Circle
{
// Указывается что это поле доступно из любого класса, даже из другой сборки
// Также можно указать protected - поле будет доступно только из классов-
// наследников и private - доступно только из текущего класса.
public int x=0;
public int y=0;
public int radius=3;
public const double pi = 3.14;
public static string name = "Окружность";
double p;
double s;
}
class Program
{
static void Main()
{
Circle cr = new Circle(); //создание экземпляра класса
Console.WriteLine("pi=" + Circle.pi);// обращение к константе
Console.Write(Circle.name);// обращение к статическому полю
//обращение к обычным полям
Console.WriteLine(" с центром в точке ({0},{1}) и радиусом {2}", cr.x, cr.y, cr.radius);
// Console.WriteLine(cr.p); - вызовет ошибку, т.к. поле p, c имеют тип private
Console.Write("Введите коэффициент= ");
int kof = int.Parse(Console.ReadLine());
cr.x -= kof; cr.y += kof; cr.radius *= kof;
Console.WriteLine(" Новая окружность с центром в точке ({0},{1}) и радиусом {2}",
cr.x, cr.y, cr.radius);
//cr.s = 2 * Circle.pi * cr.radius; - вызовет ошибку, т.к. поле s, c имеют тип private
}
}
Также можно объявить поле как readonly - запрещается запись в поле, кроме как при инициализации посредством инициализатора или конструктора.
public class MyClass
{
// Присваиваем начальное значение в инициализаторе
readonly int a = 1;
// Присваиваем начальное значение в конструкторе
public MyClass(){ a = 3; }
public MyMethod(){ a = 5; } // Ошибка компиляции
}