- •Роль инкапсуляции
- •Роль наследования
- •Роль полиморфизма
- •Конструкторы
- •Конструктор копирования
- •Деструкторы
- •Перегрузка методов
- •Перегрузка операторов
- •Перегрузка бинарных операторов
- •Перегрузка унарных операторов
- •Выполнение операций со встроенными в с# типами данных
- •Переопределение методов Перекрытие методов
- •Сокрытие методов
- •Вызов базовых версий методов
- •Область видимости переменных
- •Конфликты областей видимости локальных переменных
- •Конфликты областей видимости полей и локальных переменных
- •Константы
- •Модификаторы доступа
- •Пространства имен
- •Uml. Диаграмма вариантов использования. Привести пример.
- •Чтение схем вариантов использования
- •Субъекты, варианты использования и подсистемы
- •Структурирование вариантов использования
- •Количество элементов между субъектами и вариантами использования
- •Задание количества элементов в ассоциации
- •Uml. Диаграмма классов. Привести пример.
- •Типы атрибутов и операций
- •Несколько типов
- •Атрибуты и ассоциации
- •Обобщение
- •Реализация
- •Uml. Диаграмма последовательности. Привести пример.
- •Создание схемы последовательностей
- •Изменение порядка сообщений
- •Перемещение или копирование последовательностей сообщений на схеме последовательностей
- •Оптимизация размещения элементов на схеме последовательностей
- •Изменить пакет, владеющий взаимодействием
- •Типы сообщений
- •Создание заметок о взаимодействиях
- •Инициирующее событие
- •Уровень детализации
- •Uml. Диаграмма деятельности. Привести пример. Простые потоки управления
- •Параллельные потоки
- •Потоки данных
- •Основные этапы создания схем активности
- •Uml. Диаграмма кооперации. Привести пример.
- •Uml. Диаграмма состояний. Привести пример.
- •Понятие состояния объекта
- •Переход
- •Сложные переходы
- •Переходы между параллельными состояниями
- •Переходы между составными состояниями
- •Синхронизирующие состояния
- •Uml. Диаграмма компонентов. Диаграмма развертывания. Привести пример.
- •Структурный паттерн проектирования «Компоновщик». Привести пример.
- •Структурный паттерн проектирования «Оболочка». Привести пример.
- •Структурный паттерн проектирования «Мост». Привести пример.
- •Структурный паттерн проектирования «Адаптер». Привести пример.
- •Структурный паттерн проектирования «Заместитель». Привести пример.
- •Структурный паттерн проектирования «Приспособленец». Привести пример.
- •Поведенческий паттерн проектирования «Команда». Привести пример.
- •Поведенческий паттерн проектирования «Наблюдатель». Привести пример.
- •Поведенческий паттерн проектирования «Состояние». Привести пример.
- •Поведенческий паттерн проектирования «Итератор». Привести пример.
- •Поведенческий паттерн проектирования «Цепочка обязанностей». Привести пример.
- •Поведенческий паттерн проектирования «Шаблонный метод». Привести пример.
- •Порождающий паттерн проектирования «Абстрактная фабрика». Привести пример.
- •Порождающий паттерн проектирования «Абстрактный метод». Привести пример.
- •Порождающий паттерн проектирования «Одиночка». Привести пример.
- •Порождающий паттерн проектирования «Прототип». Привести пример.
- •Порождающий паттерн проектирования «Строитель». Привести пример
- •Архитектурный шаблон проектирование mvc. Привести пример. Введение
- •«Оригинальный» mvc
- •Model (Модель)
- •View (Представление)
- •Controller (Контроллер)
- •Недостатки mvc и Document-View
- •Почему интерфейс?
- •Отличия от mvc
- •Заключение
Конфликты областей видимости полей и локальных переменных
В некоторых случаях два идентификатора с одинаковыми именами (хотя и не совпадающими полностью уточненными именами) и одинаковой областью видимости можно различить, и тогда компилятор допускает объявление второй переменной. Причина в том, что С# делает принципиальное различие между переменными, объявленными на уровне типа (полями) и переменными, объявленными в методах (локальными). Рассмотрим следующий фрагмент кода:
using System;
namespace ConsoleApplication1
{
class Program
{
static int j = 20;
public static void Main()
{
int j = 30;
Console.WriteLine(j);
return;
}
}
Этот код компилируется, несмотря на то, что здесь в контексте метода Main() присутствуют две переменных с именем j: переменная j, определенная на уровне класса и существующая до тех пор, пока не будет уничтожен класс (когда завершится метод Main(), а вместе с ним и программа), и переменная j, определенная внутри Main(). В данном случае новая переменная с именем j, объявленная в методе Main(), скрывает переменную уровня класса с тем же именем. Поэтому когда вы запустите этот код, на дисплее будет отображено число 30.
Константы
Как следует из названия, константа — это переменная, значение которой не меняется за время ее существования. Предваряя переменную ключевым словом const при ее объявлении и инициализации, вы объявляете ее как константу:
const int a = 100; // Это значение не может быть изменено
Ниже перечислены основные характеристики констант:
Они должны инициализироваться при объявлении, и однажды присвоенные им значения никогда не могут быть изменены.
Значение константы должно быть вычислено во время компиляции. Таким образом, инициализировать константу значением, взятым из другой переменной, нельзя. Если все-таки нужно это сделать, используйте поля только для чтения.
Константы всегда неявно статические. Однако вы не должны (и фактически не можете) включать модификатор static в объявление константы.
Использование констант в программах обеспечивает, по крайней мере, три преимущества:
Константы облегчают чтение программ, заменяя "магические" числа и строки читаемыми именами, назначение которых легко понять.
Константы облегчают модификацию программ. Например, предположим, что в программе С# имеется константа SalesTax (налог с продаж), которой присвоено значение 6 процентов. Если налог с продаж когда-нибудь изменится, вы можете модифицировать все вычисления налога, просто присвоив новое значение этой константе, и не понадобится просматривать код в поисках значений О.О6 изменять каждое из них, надеясь, что оно нигде не будет пропущено.
Константы позволяют избежать ошибок в программах. Если попытаться присвоить новое значение константе где-то в другом месте программы, а не там, где она объявлена, компилятор выдаст сообщение об ошибке.
Модификаторы доступа
Модификаторы доступа – это ключевые слова, задающие объявленную доступность члена или типа. В этой главе описано четыре модификатора доступа.
public
Ключевое слово public является модификатором доступа для типов и членов типов. Общий (public) доступ является уровнем доступа с максимальными правами. Ограничений доступа к общим членам не существует, как показано в следующем примере:
Копировать
class SampleClass
{
public int x; // No access restrictions.
}
Дополнительные сведения см. в разделах Модификаторы доступа (Руководство по программированию в C#) и Уровни доступности (Справочник по C#).
Пример
В следующем примере объявляются два класса: PointTest и MainClass. Доступ к общим членам x и y класса PointTest осуществляется непосредственно из класса MainClass.
C#
Копировать
class PointTest
{
public int x;
public int y;
}
class MainClass4
{
static void Main()
{
PointTest p = new PointTest();
// Direct access to public members:
p.x = 10;
p.y = 15;
Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
}
}
// Output: x = 10, y = 15
Если уровень доступа public изменить на private или protected, то в результате будет выводиться следующее сообщение об ошибке:
Доступ к элементу "PointTest.y" невозможен из-за его уровня защиты.
protected
Ключевое слово protected является модификатором доступа к члену. Доступ к члену с модификатором protected возможен внутри класса и из производных экземпляров класса. Для сравнения ключевого слова protected с другими модификаторами доступа см. раздел Уровни доступности.
Пример
Член базового класса с модификатором protected доступен в производном классе только в том случае, если доступ осуществляется через тип производного класса. В качестве примера рассмотрим следующий фрагмент кода:
C#
Копировать
class A
{
protected int x = 123;
}
class B : A
{
static void Main()
{
A a = new A();
B b = new B();
// Error CS1540, because x can only be accessed by
// classes derived from A.
// a.x = 10;
// OK, because this class derives from A.
b.x = 10;
}
}
Оператор a.x = 10 генерирует ошибку, поскольку он произведен внутри статического метода Main, а не внутри экземпляра класса B.
Элементы структур не могут использоваться с модификатором protected, потому что наследование от структуры невозможно.
В этом примере класс DerivedPoint является производным от класса Point. Следовательно, доступ к членам базового класса с модификатором protected можно осуществлять непосредственно из производного класса.
C#
Копировать
class Point
{
protected int x;
protected int y;
}
class DerivedPoint: Point
{
static void Main()
{
DerivedPoint dpoint = new DerivedPoint();
// Direct access to protected members:
dpoint.x = 10;
dpoint.y = 15;
Console.WriteLine("x = {0}, y = {1}", dpoint.x, dpoint.y);
}
}
// Output: x = 10, y = 15
Если изменить уровень доступа к переменным x и y на private, то компилятор выдаст следующие сообщения об ошибке:
'Point.y' is inaccessible due to its protection level.
'Point.x' is inaccessible due to its protection level.
internal
Ключевое слово internalмодификатор доступа для типов и членов типов. Внутренние типы или члены доступны только внутри файлов в одной и той же сборке (см. следующий пример).
Копировать
public class BaseClass
{
// Only accessible within the same assembly
internal static int x = 0;
}
Доступ к типам или членам с модификатором доступа protected internal может осуществляться из текущей сборки или из типов, которые являются производными от содержащего их класса.
Сравнение модификатора internal с другими модификаторами доступа см. в разделах Уровни доступности (Справочник по C#) и Модификаторы доступа (Руководство по программированию в C#).
Дополнительные сведения о сборках см. в разделе Сборки и глобальный кэш сборок (C# и Visual Basic).
Внутренний доступ чаще всего используется в разработке на основе компонентов, так как он позволяет группе компонентов взаимодействовать в закрытой форме, не открывая доступ остальной части кода приложения. Например, структура для построения графических пользовательских интерфейсов может предоставлять классы Control и Form, взаимодействующие при помощи членов с внутренним доступом. Так как эти члены являются закрытыми, они не предоставляются коду, использующему структуру.
Создание ссылки на тип или член с внутренним доступом за пределами сборки, в которой он был определен, приведет к ошибке.
Пример
В этом примере содержится два файла: Assembly1.cs и Assembly1_a.cs. Первый файл содержит внутренний базовый класс BaseClass. Попытка создания экземпляра BaseClass во втором файле приведет к ошибке.
Копировать
// Assembly1.cs
// Compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
Копировать
// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
В этом примере используются те же файлы, что и в примере 1, но уровень доступности BaseClass изменен на public. Кроме того, уровень доступности члена IntM изменен на internal. В этом случае можно создать экземпляр класса, но доступ к внутреннему члену отсутствует.
Копировать
// Assembly2.cs
// Compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
Копировать
// Assembly2_a.cs
// Compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
private
Ключевое слово private является модификатором доступа к члену. Закрытый (private) доступ является уровнем доступа с минимальными правами. Доступ к закрытым членам можно получить только внутри тела класса или структуры, в которой они объявлены, как показано в следующем примере:
Копировать
class Employee
{
private int i;
double d; // private access by default
}
Вложенные типы в том же теле могут также обращаться к таким закрытым членам.
Ошибка времени компиляции возникнет в том случае, если создать ссылку на закрытый член за пределами класса или структуры, в которой он объявлен.
Сравнение модификатора private с другими модификаторами доступа см. в разделах Уровни доступности (Справочник по C#) и Модификаторы доступа (Руководство по программированию в C#).
Пример
В этом примере класс Employee содержит два закрытых элемента данных – name и salary. Как к закрытым членам, к ним нельзя получить доступ кроме как через методы членов. Для получения управляемого доступа к закрытым членам можно использовать методы с именем GetName и Salary. Доступ к методу name можно получить через открытый метод, а к методу salary – через открытое свойство только для чтения. (Дополнительные сведения см. в разделе Свойства (Руководство по программированию в C#).)
C#
Копировать
class Employee2
{
private string name = "FirstName, LastName";
private double salary = 100.0;
public string GetName()
{
return name;
}
public double Salary
{
get { return salary; }
}
}
class PrivateTest
{
static void Main()
{
Employee2 e = new Employee2();
// The data members are inaccessible (private), so
// they can't be accessed like this:
// string n = e.name;
// double s = e.salary;
// 'name' is indirectly accessed via method:
string n = e.GetName();
// 'salary' is indirectly accessed via property
double s = e.Salary;
}
}
При помощи модификаторов доступа можно задать следующие пять уровней доступности:
public : Неограниченный доступ.
protected : Доступ ограничен содержащим классом или типами, которые являются производными от содержащего класса.
Internal : Доступ ограничен текущей сборкой.
protected internal: Доступ ограничен пределами сборки или типа, который является производным от данного класса.
private : Доступ ограничен содержащим типом.