Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Понятие «модификатор доступа»

Поиск

 

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

· public ― доступ к типу или члену возможен из любого другого кода в той же сборке или другой сборке, ссылающейся на него. Открытый доступ.

· private ― доступ к типу или члену можно получить только из кода в том же классе или структуре. Закрытый доступ.

· protected ― доступ к типу или элементу можно получить только из кода в том же классе или структуре, либо в производном классе. Защищённый доступ.

· internal ― доступ к типу или члену возможен из любого кода в той же сборке, но не из другой сборки. Внутренний доступ.

· protected internal ― доступ к типу или элементу может осуществляться любым кодом в сборке, в которой он объявлен, или из наследованного класса другой сборки. Доступ из другой сборки должен осуществляться в пределах объявления класса, производного от класса, в котором объявлен защищённый внутренний элемент, и должен происходить через экземпляр типа производного класса. Защищённый внутренний доступ.

 

Не все модификаторы доступа могут использоваться всеми типами или членами во всех контекстах, а в некоторых случаях доступность члена типа ограничивается доступностью его содержащего типа. Следующие подразделы содержат дополнительные сведения о доступности.

 

Доступность класса и структуры

 

Классы и структуры, объявленные непосредственно в пространстве имён (другими словами, не вложенные в другие классы или структуры) могут быть открытыми или внутренними. Если модификатор доступа не указан, по умолчанию используется внутренний тип.

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

Производные классы могут обладать лучшей доступностью, чем их базовые типы. Другими словами, открытый класс B, являющийся производным от внутреннего класса A, не может использоваться. Его использование может быть приравнено к переводу класса A в открытый тип, поскольку все защищённые или внутренние члены A доступны из производного класса.

При помощи InternalsVisibleToAttribute можно сделать возможным доступ других определённых сборок к внутренним типам. Дополнительные сведения можно получить разделе Дружественные сборки (C# и Visual Basic) (http://msdn.microsoft.com/ru-ru/library/0tke9fxk.aspx).

 

Доступность члена класса и структуры

 

Члены класса (включая вложенные классы и структуры) можно объявить с любым из пяти типов доступа. Члены структуры нельзя объявлять защищёнными, так как структуры не поддерживают наследование.

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

Тип любого элемента, являющегося полем (переменной), свойством или событием, должен, по меньшей мере, быть таким же доступным, как и этот элемент. Аналогичным образом тип возвращаемого значения и типы параметров любого члена, который является методом, индексатором или делегатом, должны иметь, по меньшей мере, такой же уровень доступности, как сам элемент. Например, метод M, возвращающий класс C не может быть открытым, если C также не является открытым. Подобным образом, свойство типа A не может быть защищенным, если A объявлен внутренним.

Определённые пользователям операторы (перегруженные операторы) также должны быть объявлены как открытые.

Деструкторы не могут иметь модификаторов доступности.

 

Чтобы задать уровень доступа для класса или элемента структуры, необходимо использовать соответствующим ключевым словом в объявлении элемента, как показано в следующем примере:

 

// public класс

public class Tricycle

{

// protected метод

protected void Pedal() { }

 

// private поле (переменная)

private int wheels = 3;

 

// protected internal свойство

protected internal int Wheels

{

get { return wheels; }

}

}

 

Защищённый внутренний уровень доступности означает «защищённый или внутренний», а не «защищённый и внутренний». Другими словами, доступ к защищённому внутреннему члену может осуществляться из любого класса в одной сборке, в том числе из производных классов. Чтобы ограничить доступность только производными классами в одной и той же сборке, сам класс необходимо объявить внутренним, а его члены ― защищёнными.

 

Другие типы

 

Интерфейсы, объявленные непосредственно в пространстве имён, можно объявить как открытые или внутренние, и подобно классам и структурам, интерфейсам по умолчанию присваивается внутренний доступ. Члены интерфейса всегда являются открытыми, поскольку целью интерфейса является предоставление возможности доступа к классу или структуре другим типам. Модификаторы доступа нельзя применить к членам интерфейса.

Члены перечисления всегда являются открытыми, и модификаторы доступа не применяются.

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

Понятие «Класс» и «Статический класс»

Понятие «Класс» и «Статический класс»

 

Понятие «класс»

 

Класс — это конструктор, который позволяет создавать свои собственные пользовательские типы путем группирования переменных других типов, методов и событий. Класс подобен чертежу. Он определяет данные и поведение типа. Если класс не объявлен статическим, то клиентский код может его использовать, создав объекты или экземпляры, назначенные переменной. Переменная остаётся в памяти, пока все ссылки на нее не выйдут из области видимости. В это время среда CLR помечает её пригодной для сборщика мусора. Если класс объявляется статическим, то в памяти остается только одна копия и клиентский код может получить к ней доступ только посредством самого класса, а не переменной экземпляра.

Итак, класс — это что-то наподобие шаблона, по которому будут создаваться объекты. Что-то наподобие литейных форм, для выплавки металлических изделий. Необходимо один раз создать класс, после чего можно создать бесконечное число (сколько памяти хватит) идентичных объектов.

 

В отличие от структур, классы поддерживают наследование, фундаментальную характеристику объектно-ориентированного программирования.

 

Объявление классов

 

Классы объявляются с помощью ключевого слова class, как показано в следующем примере:

 

public class MyClass

{

// Свойства, методы, события, поля (переменные) и прочее...

}

 

Ключевому слову class предшествует уровень доступа. Поскольку в данном случае используется public, любой (в любом месте кода) может создавать объекты из этого класса. Имя класса (в данном случае MyClass) указывается после ключевого слова class. Оставшаяся часть определения является телом класса, в котором задаются данные и поведение. свойства, методы, события и поля в классе обозначаются термином члены класса.

 

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

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

 

Рис. 2. 1. Структура данных класса

 

Данные-члены — это те члены, которые содержат данные класса — поля, константы,события. Данные-члены могут быть статическими (static). Член класса является членом экземпляра, если только он не объявлен явно как static. Давайте рассмотрим виды этих данных:

Поля (field) —это любые переменные, ассоциированные с классом.

Константы — могут быть ассоциированы с классом тем же способом, что и переменные. Константа объявляется с помощью ключевого слова const. Если она объявлена как public, то в этом случае становится доступной извне класса.

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

Функции-члены — это члены, которые обеспечивают некоторую функциональность для манипулирования данными класса. Они включают методы, свойства, конструкторы, финализаторы, операции и индексаторы:

Методы (method)— это функции, ассоциированные с определенным классом. Как и данные-члены, по умолчанию они являются членами экземпляра. Они могут быть объявлены статическими с помощью модификатора static.

Свойства (property)— это наборы функций, которые могут быть доступны клиенту таким же способом, как общедоступные поля класса. В С# предусмотрен специальный синтаксис для реализации чтения и записи свойств для классов, поэтому писать собственные методы с именами, начинающимися на Set и Get, не понадобится. Поскольку не существует какого-то отдельного синтаксиса для свойств, который отличал бы их от нормальных функций, создается иллюзия объектов как реальных сущностей, предоставляемых клиентскому коду.

Конструкторы (constructor)— это специальные функции, вызываемые автоматически при инициализации объекта. Их имена совпадают с именами классов, которым они принадлежат, и они не имеют типа возврата. Конструкторы полезны для инициализации полей класса.

Финализаторы (finalizer)— вызываются, когда среда CLR определяет, что объект больше не нужен. Они имеют то же имя, что и класс, но с предшествующим символом тильды. Предсказать точно, когда будет вызван «финализатор», невозможно.

Операции (operator)— это простейшие действия вроде + или -. Когда вы складываете два целых числа, то, строго говоря, применяете операцию + к целым. Однако С# позволяет указать, как существующие операции будут работать с пользовательскими классами (так называемая перегрузка операции).

Индексаторы (indexer)— позволяют индексировать объекты таким же способом, как массив или коллекцию.

 

Как уже говорилось выше, класс создаётся с помощью ключевого слова class. Ниже приведена общая форма определения простого класса, содержащая только переменные экземпляра и методы:

 

class <имя класса>

{

// Объявление переменных экземпляра

<модификатор доступа> <тип переменной> <переменная1>;

<модификатор доступа> <тип переменной> <переменная2>;

//...

<модификатор доступа> <тип переменной> <переменнаяX>;

// Объявление <методов

<модификатор доступа> <возвращаемый тип переменной> <метод1> (<параметры>)

{

// Тело <метода

}

<модификатор доступа> <возвращаемый тип переменной> <метод2> (<параметры>)

{

// Тело <метода

}

//...

<модификатор доступа> <возвращаемый тип переменной> <методы> (<параметры>)

{

// Тело <метода

}

}

 

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

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LC_Console

{

class UserInfo

{

// Поля класса

public string Name, Family, Adress;

public byte Age;

// Метод, выводящий в консоль контактную информацию

public void writeInConsoleInfo(string name, string family, string adress, byte age)

{

Console.WriteLine("Имя: {0}\nФамилия: {1}\nМестонахождение: {2}\nВозраст: {3}\n", name, family, adress, age);

}

}

 

class Program

{

static void Main()

{

// Создаём объект типа UserInfo

UserInfo myInfo = new UserInfo();

myInfo.Name = "Vladimir";

myInfo.Family = "P.";

myInfo.Adress = "Moscow";

myInfo.Age = 59;

// Создаём новый экземпляр класса UserInfo

UserInfo myGirlFriendInfo = new UserInfo();

myGirlFriendInfo.Name = "Anna";

myGirlFriendInfo.Family = "C.";

myGirlFriendInfo.Adress = "Moscow";

myGirlFriendInfo.Age = 20;

// Выведем информацию в консоль

myInfo.writeInConsoleInfo(myInfo.Name, myInfo.Family, myInfo.Adress, myInfo.Age);

myGirlFriendInfo.writeInConsoleInfo(myGirlFriendInfo.Name, myGirlFriendInfo.Family, myGirlFriendInfo.Adress, myGirlFriendInfo.Age);

Console.WriteLine("Для продолжения нажмите любую клавишу... ");

Console.ReadKey();

}

}

}

 

Рис. 2. 2. Результат работы кода выше

 

Создание экземпляра класса

 

Класс и экземпляр (объект) — это разные вещи, хотя в некоторых случаях они взаимозаменяемы. Класс определяет тип объекта, но не сам объект. Объект — это конкретная сущность, основанная на классе и иногда называемая экземпляром класса.

Объекты можно создавать с помощью ключевого слова new, за которым следует имя класса, на котором будет основан объект:

 

MyClass myClass1 = new MyClass();

 

При создании экземпляра класса, ссылка на этот объект передаётся программисту. В предыдущем примере myClass1 является ссылкой на объект, основанный на MyClass. Эта ссылка указывает на новый объект, но не содержит данные этого объекта. Фактически, можно создать ссылку на объект без создания самого объекта:

 

MyClass myClass1;

 

Создание таких ссылок, которые не указывают на объект, не рекомендуется, так как попытка доступа к объекту по такой ссылке приведет к выдаче ошибки (исключения) во время выполнения. Однако такую ссылку можно сделать указывающей на объект, создав новый объект или назначив её существующему объекту:

 

MyClass myClass1 = new MyClass();

MyClass myClass2 = myClass1;

 

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

 

Наследование классов

 

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

 

public class SecondMyClass: MyClass

{

//...

}

 

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

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

 

Класс может быть объявлен абстрактным (abstract). Абстрактный класс содержит абстрактные методы, которые имеют определение сигнатуры, но не имеют реализации. Создавать абстрактные классы нельзя. Они могут использоваться только посредством производных классов, реализующих абстрактные методы. И наоборот, запечатанный (sealed) класс не позволяет другим классам быть от него производными. Также класс можно разделить между файлами. Это р азделяемый класс (partial).

 

Пример класса с переменной и методом, а также использование этого метода в консольном приложении:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LC_Console

{

public class Person

{

// Переменная

public string name;

// Конструктор

public Person()

{

name = "Неизвестно";

}

// Метод

public void SetName(string newName)

{

name = newName;

}

}

 

class TestPerson

{

static void Main()

{

Person person = new Person();

Console.WriteLine(person.name);

person.SetName("John A.");

Console.WriteLine(person.name);

/*

* Выведет:

* Неизвестно

* John A.

*/

Console.WriteLine("Для продолжения нажмите любую клавишу... ");

Console.ReadKey();

}

}

}

 

В отличие от C++, в C# допускается только одиночное наследование. Другими словами, класс может наследовать реализацию только от одного базового класса. Однако класс может реализовать несколько интерфейсов. В приведённой ниже таблице приведены примеры наследования класса и реализации интерфейса:

 

Наследование Пример
Нет class ClassA { }
Single class DerivedClass: BaseClass { }
Отсутствует, реализует два интерфейса class ImplClass: IFace1, IFace2 { }
Одиночное, реализует один интерфейс class ImplDerivedClass: BaseClass, IFace1 { }

 



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 437; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.104.18 (0.01 с.)