Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лр-2(Классы).docx
Скачиваний:
3
Добавлен:
16.08.2019
Размер:
142.88 Кб
Скачать

Определение членов

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

public (общедоступный) — делает члены доступными из любого кода.

private (приватный) — делает члены доступными только из того кода, который является частью данного класса (используется по умолчанию, если не указывается никакое ключевое слово).

internal (внутренний) - делает челны доступными только из кода проекта (сборки), внутри которого они определяются.

protected (защищенный) — делает члены доступными только из того кода, который является частью либо данного класса, либо класса, производного от него.

Два последних ключевых слова могут комбинироваться, т.е. также существуют и члены protected internal. Такие члены доступны только из классов, которые являются производными от кода, содержащегося внутри проекта (а точнее — внутри сборки).

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

Определение полей

Поля определяются с применением стандартного формата объявления переменных (и, при желании, инициализации), а также перечисленных выше модификаторов:

class MyClass

{

public int Mylnt;

}

При определении полей также может использоваться ключевое слово readonly, означающее, что данному полю значение может присваиваться только либо во время выполнения кода конструктора, либо посредством операции начального присваивания:

class MyClass

{

public readonly int Mylnt = 17 ;

}

Поля могут объявляться статическими с использованием ключевого слова static:

class MyClass

{

public static int Mylnt;

}

К статическим полям доступ осуществляется через класс, в котором они определяются (в предыдущем примере таковым является класс MyClass .Mylnt), а не через экземпляры объектов этого класса. Для создания константных значений служит ключевое слово const. Члены const являются статическими по определению, поэтому в их случае применять модификатор static не нужно (на самом деле это будет считаться ошибкой).

Определение методов

При определении методов применяется стандартный формат определения функций, но также указывается уровень доступности и, при желании, модификаторы static, как показано в следующем примере:

class MyClass {

public string GetString() {

return "Here is a string."; //(Вот строка)

}

}

Запомните, что указание ключевого слова static делает метод доступным только через класс, в котором он определяется, но не через экземпляры объектов этого класса. При определении методов могут еще использоваться и следующие ключевые слова.

□ virtual (виртуальный) — указывает, что данный метод может переопределяться.

□ abstract (абстрактный) — указывает, что данный метод должен обязательно переопределяться в не абстрактных производных классах (может использоваться только в абстрактных классах).

□ override (переопределенный) — указывает, что данный метод переопределяет какой-то метод, определенный в базовом классе.

□ extern (внешний) — указывает, что определение данного метода находится в каком-то другом месте.

Ниже приведен пример переопределения метода:

public class MyBaseClass

{

public virtual void DoSomething ()

{

// Базовая реализация.

}

}

public class MyDerivedClass : MyBaseClass

{

public override void DoSomething ()

{

// Реализация в производном классе, переопределяющая базовую реализацию.

}

}

Вместе с ключевым словом override может также использоваться и ключевое слово sealed (герметизированный), указывающее, что в данный метод больше не могут вноситься изменения ни в каких производных классах, т.е. метод не может переопределяться в производных классах. Ниже приведен пример:

public class MyDerivedClass : MyBaseClass

{

public override sealed void DoSomething ()

{

// Реализация в производном классе, переопределяющая базовую реализацию.

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

Определение свойств

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

Эти блоки, также называемые средствами доступа (accessors), определяются с помощью, соответственно, ключевого слова get и ключевого слова set и могут применяться для управления уровнем доступа к свойству. Можно опускать тот или иной из них и тем самым создавать свойства, доступные только для записи или только для чтения (в частности, пропуск блока get позволяет обеспечивать доступ только для записи, а пропуск блока set — доступ только для чтения). Разумеется, это касается только внешнего кода, поскольку у кода внутри класса будет доступ к тем же данным, что и у этих блоков кода. Еще можно использовать со средствами доступа модификаторы доступности, т.е. делать, например, блок get общедоступным (public), а блок set — защищенным (protected). Для получения действительного свойства нужно обязательно включать хотя бы один из этих блоков (очевидно, что от свойства, которое нельзя ни считывать, не изменять, было бы мало толку).

Базовая структура свойства состоит из стандартного ключевого слова, указывающего на уровень доступа (такого как public, private и т.д.), за которым идет имя типа, имя свойства и один или оба блока get и set, содержащие код обработки свойства:

Public int MylntProp

{

Get

{

// Код для получения значения свойства.

}

set

{

// Код для установки значения свойства.

}

}

Первая строка в определении свойства как раз и является тем небольшим фрагментом, который очень похож на определение поля. Отличие состоит в том, что в конце строки находится не точка с запятой, а блок кода, содержащий вложенные блоки get и set.

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

// Поле, используемое свойством,

private int myInt;

// Свойство.

public int MyIntProp

{

get

{

return myInt;

}

set

{

// Код установки значения свойства.

}

}

Код, находящийся за пределами класса, не сможет получать доступ к данному полю myInt напрямую из-за того, что уровень доступности последнего указан как private. Вместо этого внешнему коду для получения доступа к этому полю придется использовать свойство. Функция set присваивает значение полю похожим образом. Здесь можно применять ключевое слово value для ссылки на значение, получаемое от пользователя свойства:

// Поле, используемое свойством,

private int myInt;

// Свойство.

public int MyIntProp

{

get

{

return myInt;

}

set

{

myInt = value;

}

}

value равно значению того же типа, что и у свойства, так что если в свойстве используется тот же тип, что в поле, беспокоиться о приведении типов не нужно.

Это простое свойство делает немного больше, чем просто защищает от прямого доступа к полю myInt. Реальная мощь свойств проявляется тогда, когда осуществляется немного больше контроля над процессами. Например, блок set мог бы быть реализован и следующим образом:

set

{

if (value > = 0 && value <= 10)

mylnt = value;

}

Эта реализация предусматривает изменение myInt только в случае присваивания свойству значения в диапазоне между 0 и 10. В ситуациях, подобных этой, требуется делать важный выбор касательно того, что должно происходить в случае использования недействительного значения. Существует четыре возможных варианта:

  • ничего (как и в предыдущем коде);

  • полю должно присваиваться значение по умолчанию;

  • выполнение кода должно продолжаться так, будто ничего страшного не произошло, но с регистрацией события в журнале для последующего анализа причин его возникновения;

  • должно генерироваться исключение.

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

set

{

if (value > = 0 && value <= 10)

mylnt = value;

else

throw (new ArgumentOutOfRangeException ("MylntProp" , value,

"MylntProp must be assigned a value between 0 and 10.")) ;

// MylntProp может присваиваться только значение в диапазоне от 0 до 10

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]