Модификатор доступа по умолчанию

Модификатор доступа по умолчанию

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

В C# применяются следующие модификаторы доступа:

public : публичный, общедоступный класс или член класса. Такой член класса доступен из любого места в коде, а также из других программ и сборок.

private : закрытый класс или член класса. Представляет полную противоположность модификатору public. Такой закрытый класс или член класса доступен только из кода в том же классе или контексте.

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

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

protected internal : совмещает функционал двух модификаторов. Классы и члены класса с таким модификатором доступны из текущей сборки и из производных классов.

private protected : такой член класса доступен из любого места в текущем классе или в производных классах, которые определены в той же сборке.

Мы можем явно задать модификатор доступа, например:

Либо можем не указывать:

Если для полей и методов не определен модификатор доступа, то по умолчанию для них применяется модификатор private .

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

Все классы и структуры, определенные напрямую в пространствах имен и не являющиеся вложенными в другие классы, могут иметь только модификаторы public или internal.

Посмотрим на примере и создадим следующий класс State:

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

Также имеются шесть методов, которые будут выводить значения полей класса на экран. Обратите внимание, что так как все модификаторы позволяют использовать члены класса внутри данного класса, то и все переменные класса, в том числе закрытые, у нас доступны всем его методам, так как все находятся в контексте класса State.

Теперь посмотрим, как мы сможем использовать переменные нашего класса в программе (то есть в методе Main класса Program), если классы State и Program находятся в одном проекте :

Таким образом, мы смогли установить только переменные internalVar, protectedInternalVar и publicVar, так как их модификаторы позволяют использовать в данном контексте.

Аналогично дело обстоит и с методами:

Здесь нам оказались доступны только три метода: internalMethod, protectedInternalMethod, publicMethod, которые имееют соответственно модификаторы internal, protected internal, public.

Благодаря такой системе модификаторов доступа можно скрывать некоторые моменты реализации класса от других частей программы.

Несмотря на то, что модификаторы public и internal похожи по своему действию, но они имеют большое отличие. Классы и члены класса с модификатором public также будут доступны и другим программам, если данных класс поместить в динамическую библиотеку dll и потом ее использовать в этих программах.

    Переводы, 22 августа 2016 в 21:08

В прошлых статьях серии “Введение в ООП” мы рассматривали полиморфизм (а также нюансы использования его на практике), наследование и абстрактные классы. В этой части я постараюсь раскрыть все тонкости использования модификаторов доступа, которые знаю сам. Продолжаем погружаться в ООП!

Что такое модификаторы доступа?

Давайте в этот раз возьмём определение из Википедии (в русской Википедии статьи access modifiers нет, поэтому здесь приводим свой перевод — прим. перев.) :

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

Модификаторы public, private, protected

Каждый раз, когда мы создаём класс, мы хотим иметь возможность определять, кто и откуда может взаимодействовать с его членами. Иными словами, нам иногда нужно ограничивать доступ к некоторым членам класса. Есть одно простое правило — члены одного класса всегда имеют доступ друг к другу. Если же говорить про доступ извне, то стоит запомнить, что модификатор доступа по умолчанию – private , т.е. все члены класса доступны только изнутри него самого.

Традиционно сразу переходим к практике. Давайте попробуем выполнить следующий код:

Результатом выполнения этого кода будет:

BBB() отмечен как public , соответственно его можно вызывать откуда угодно. Метод AAA() же никак не отмечен, значит, он является приватным. Однако для члена того же класса (ведь AAA() и BBB() принадлежат одному классу, верно?) это не имеет никакого значения.

Читайте также:  Kali linux на ios

Теперь попробуем получить доступ к AAA() напрямую:

‘AccessModifiers.Modifiers.AAA()’ is inaccessible due to its protection level

Для внешних вызовов модификатор private — непреодолимая преграда. То же самое можно сказать и о модификаторе protected .

Модификаторы доступа и наследование

Снова попробуем выполнить код:

Запускаем код и видим…

‘AccessModifiers.ModifiersBase.AAA()’ is inaccessible due to its protection level

Приватные члены недоступны даже дочерним классам. Публичные члены доступны всем, это понятно. Модификатор же protected по сути и обозначает, что член доступен только дочерним классам — вызов CCC() в примере выше не вызывает никаких ошибок.

Модификатор Internal для классов

Давайте рассмотрим следующий сценарий: мы создаём в новой библиотеке классов (назовём её AccessModifiersLibrary ) класс ClassA и помечаем его как internal :

Теперь в созданном ранее файле попробуем выполнить:

Compile time error: ‘AccessModifiersLibrary.ClassA’ is inaccessible due to its protection level

Мы встретили эту ошибку из-за спецификатора доступа internal , который обозначает, что ClassA доступен только внутри AccessModifiersLibrary и ниоткуда больше. Впрочем, если мы уберём этот модификатор, ничего не изменится — internal является спецификатором по умолчанию.

Модификаторы для пространств имён

Давайте попробуем сделать с предыдущим кодом следующее:

Конечно, это не скомпилируется:

Compile time error: A namespace declaration cannot have modifiers or attributes

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

Приватные классы

Если мы попробуем скомпилировать код, приведённый выше, то получим ошибку:

Compile time error: Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal

Всё правильно: классы могут быть либо public , либо internal .

Подробнее о модификаторах членов класса

Что будет, если мы захотим назначить члену класса больше одного модификатора доступа?

Будет ошибка компиляции:

Compile time error: More than one protection modifier

А как поведёт себя язык, если мы создадим public метод в internal классе?

Вывод после компиляции:

‘AccessModifiersLibrary.ClassA’ is inaccessible due to its protection level

The type ‘AccessModifiersLibrary.ClassA’ has no constructors defined

‘AccessModifiersLibrary.ClassA’ is inaccessible due to its protection level

‘AccessModifiersLibrary.ClassA’ does not contain a definition for ‘MethodClassA’ and
no extension method ‘MethodClassA’ accepting a first argument of type ‘AccessModifiersLibrary.ClassA’
could be found (are you missing a using directive or an assembly reference?)

Как много ошибок… Дело в том, что какими бы модификаторами не обладали члены internal класса, их всё равно нельзя вызвать оттуда, где не виден сам класс. А что будет, если мы попробуем сделать наоборот — вызвать private или internal метод у public класса?

‘AccessModifiersLibrary.ClassA’ does not contain a definition
for ‘MethodClassA’ and no extension method ‘MethodClassA’ accepting a first argument
of type ‘AccessModifiersLibrary.ClassA’ could be found (are you missing a using directive or an assembly reference?)

Не-а, всё равно не работает. А если изменим модификатор метода на internal ?

‘AccessModifiersLibrary.ClassA’ does not contain a definition for ‘MethodClassA’ and no extension
method ‘MethodClassA’ accepting a first argument of type ‘AccessModifiersLibrary.ClassA’ could be
found (are you missing a using directive or an assembly reference?)

Увы, так делать тоже нельзя.

Модификатор protected internal

Этот код компилируется без ошибок. Модификатор internal proteted (как не слишком сложно догадаться) даёт понять, что метод доступен как для вызовов из того же файла, в котором он объявлен, так и для вызовов из дочерних классов.

Protected поля

Здесь всё будет немного сложнее. Давайте напишем следующий код:

Если мы его запустим, то получим ошибку:

Cannot access protected member ‘AccessModifiers.AAA.a’ via a qualifier of type ‘AccessModifiers.AAA’;
the qualifier must be of type ‘AccessModifiers.BBB’ (or derived from it)

Совершенно неочевидно, правда? Компилятор ругается на строчку aaa.a = 100 из метода MethodBBB . Почему никаких ошибок не вызывает метод MethodAAA понять достаточно просто — поле a объявлено в том же файле, в том же классе, в котором к нему и происходит обращение, это не может быть ошибкой. Почему в классе BBB доступен член bbb.a тоже понятно — модификатор protected прямо разрешает использовать члены родительского класса в дочернем как свои. Почему же вызов aaa.a = 100 из метода MethodBBB под запретом? Пожалуй, это стоит просто запомнить.

19 ноября 2019 – 10 января 2020, Гусев и онлайн, беcплатно

Все типы и члены имеют уровень доступности, определяющий возможность их использования из другого кода в вашей или в других сборках. All types and type members have an accessibility level, which controls whether they can be used from other code in your assembly or other assemblies. Следующие модификаторы доступа позволяют указать доступность типа или члена при объявлении: You can use the following access modifiers to specify the accessibility of a type or member when you declare it:

public public
Доступ к типу или члену возможен из любого другого кода в той же сборке или другой сборке, ссылающейся на него. The type or member can be accessed by any other code in the same assembly or another assembly that references it.

Читайте также:  Dragon age inquisition сколько весит

private private
Доступ к типу или члену возможен только из кода в том же классе или структуре. The type or member can be accessed only by code in the same class or struct.

protected protected
Доступ к типу или члену возможен только из кода в том же классе либо в классе, производном от этого класса. The type or member can be accessed only by code in the same class, or in a class that is derived from that class.
internal internal
Доступ к типу или члену возможен из любого кода в той же сборке, но не из другой сборки. The type or member can be accessed by any code in the same assembly, but not from another assembly.

protected internal Доступ к типу или члену возможен из любого кода в той сборке, где он был объявлен, или из производного класса в другой сборке. protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.

private protected Доступ к типу или члену возможен только из его объявляющей сборки из кода в том же классе либо в типе, производном от этого класса. private protected The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is derived from that class.

В следующих примерах показано, как изменить модификаторы доступа для типа или члена типа: The following examples demonstrate how to specify access modifiers on a type and member:

Не все модификаторы доступа могут использоваться всеми типами или членами типов во всех контекстах, а в некоторых случаях доступность члена типа ограничивается доступностью типа, в котором он содержится. Not all access modifiers can be used by all types or members in all contexts, and in some cases the accessibility of a type member is constrained by the accessibility of its containing type. Следующие подразделы содержат дополнительные сведения о доступности. The following sections provide more details about accessibility.

Доступность классов и структур Class and Struct Accessibility

Классы и структуры, объявленные непосредственно в пространстве имен (другими словами, не вложенные в другие классы или структуры), могут быть открытыми или внутренними. Classes and structs that are declared directly within a namespace (in other words, that are not nested within other classes or structs) can be either public or internal. Если модификатор доступа не указан, по умолчанию используется внутренний тип. Internal is the default if no access modifier is specified.

Члены структуры, включая вложенные классы и структуры, могут объявляться как открытые, внутренние или закрытые. Struct members, including nested classes and structs, can be declared as public, internal, or private. Члены класса, включая вложенные классы и структуры, могут объявляться как открытые, защищенные внутренние, защищенные, внутренние, защищенные закрытые или закрытые. Class members, including nested classes and structs, can be public, protected internal, protected, internal, private protected or private. По умолчанию уровень доступа к членам класса и членам структуры, включая вложенные классы и структуры, является закрытым. The access level for class members and struct members, including nested classes and structs, is private by default. Закрытые вложенные типы недоступны за пределами типа, в котором содержатся. Private nested types are not accessible from outside the containing type.

Производные классы не могут быть более доступны, чем соответствующие базовые типы. Derived classes cannot have greater accessibility than their base types. Другими словами, нельзя иметь открытый класс B , производный от внутреннего класса A . In other words, you cannot have a public class B that derives from an internal class A . Если бы это было возможно, класс A стал бы открытым, поскольку все защищенные или внутренние члены класса A были бы доступны из производного класса. If this were allowed, it would have the effect of making A public, because all protected or internal members of A are accessible from the derived class.

Доступ к внутренним типам можно предоставить некоторым другим сборкам с помощью класса InternalsVisibleToAttribute. You can enable specific other assemblies to access your internal types by using the InternalsVisibleToAttribute. Дополнительные сведения см. в разделе Дружественные сборки. For more information, see Friend Assemblies.

Доступность членов классов и структур Class and Struct Member Accessibility

Члены класса (включая вложенные классы и структуры) можно объявлять с любым из шести типов доступа. Class members (including nested classes and structs) can be declared with any of the six types of access. Члены структуры нельзя объявлять как защищенные, поскольку структуры не поддерживают наследование. Struct members cannot be declared as protected because structs do not support inheritance.

Читайте также:  Как перевести текст в заглавные буквы

Как правило, уровень доступности члена не может быть выше уровня доступности типа, в который он входит. Normally, the accessibility of a member is not greater than the accessibility of the type that contains it. При этом открытый член внутреннего класса может быть доступен за пределами сборки, если он реализует методы интерфейса или переопределяет виртуальные методы, определенные в открытом базовом классе. However, a public member of an internal class might be accessible from outside the assembly if the member implements interface methods or overrides virtual methods that are defined in a public base class.

Тип любого члена, который является полем, свойством или событием, должен иметь, как минимум, такой же уровень доступности, как у самого члена. The type of any member that is a field, property, or event must be at least as accessible as the member itself. Точно так же тип возвращаемого значения и типы параметров любого члена, который является методом, индексатором или делегатом, должен иметь, как минимум, такой же уровень доступности, как у самого члена. Similarly, the return type and the parameter types of any member that is a method, indexer, or delegate must be at least as accessible as the member itself. Например, нельзя иметь открытый метод M , возвращающий класс C , если C не является также открытым. For example, you cannot have a public method M that returns a class C unless C is also public. Аналогичным образом нельзя иметь защищенное свойство типа A , если A объявлен как закрытый. Likewise, you cannot have a protected property of type A if A is declared as private.

Пользовательские операторы всегда должны объявляться как открытые и статические. User-defined operators must always be declared as public and static. Для получения дополнительной информации см. раздел Перегрузка операторов. For more information, see Operator overloading.

Методы завершения не могут иметь модификаторы доступа. Finalizers cannot have accessibility modifiers.

Чтобы настроить уровень доступа для члена класса или структуры, добавьте в объявление этого члена соответствующее ключевое слово, как показано в следующем примере. To set the access level for a class or struct member, add the appropriate keyword to the member declaration, as shown in the following example.

Защищенный внутренний уровень доступности означает защищенный ИЛИ внутренний доступ, а не защищенный И внутренний. The protected internal accessibility level means protected OR internal, not protected AND internal. Другими словами, защищенный внутренний член доступен из любого класса в той же сборке, включая производные классы. In other words, a protected internal member can be accessed from any class in the same assembly, including derived classes. Чтобы сделать его доступным только для производных классов в той же сборке, объявите сам класс как внутренний, а его члены как защищенные. To limit accessibility to only derived classes in the same assembly, declare the class itself internal, and declare its members as protected. Кроме того, начиная с C# 7.2, можно использовать защищенные закрытые модификаторы доступа для достижения такого же результата без необходимости преобразования содержащего класса во внутренний. Also, starting with C# 7.2, you can use the private protected access modifier to achieve the same result without need to make the containing class internal.

Другие типы Other Types

Интерфейсы, объявляемые непосредственно в пространстве имен, могут быть объявлены как открытые или внутренние. Равно как и в случае с классами и структурами, для интерфейсов по умолчанию задается внутренний доступ. Interfaces declared directly within a namespace can be declared as public or internal and, just like classes and structs, interfaces default to internal access. Члены интерфейса всегда открыты, поскольку интерфейс как раз и создан для того, чтобы обеспечить доступ к классу или структуре для других типов. Interface members are always public because the purpose of an interface is to enable other types to access a class or struct. Модификаторы доступа к членам интерфейса не применяются. No access modifiers can be applied to interface members.

Члены перечисления всегда открыты, и модификаторы доступа к ним не применяются. Enumeration members are always public, and no access modifiers can be applied.

Делегаты ведут себя как классы и структуры. Delegates behave like classes and structs. По умолчанию они имеют внутренний доступ, если объявляются непосредственно в пространстве имен, и закрытый доступ, если являются вложенными. By default, they have internal access when declared directly within a namespace, and private access when nested.

Спецификация языка C# C# Language Specification

Дополнительные сведения см. в спецификации языка C#. For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#. The language specification is the definitive source for C# syntax and usage.

Ссылка на основную публикацию
Adblock detector