Вложенные классы. Вложенные статические классы. Объявление и использование вложенных классов. Примеры

Вложенные классы. Вложенные статические классы. Объявление и использование вложенных классов. Примеры


Содержание



1. Понятие вложенного класса. Общая форма объявления вложенного класса

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

В простейшем случае, общая форма объявления вложенного класса в классе имеет вид:

// класс, который содержит в реализации объявление другого класса
class Outer
{
  // поля и методы класса Outer
  // ...

  class Inner
  {
    // поля и методы класса Inner
    // ...
  }

  // поля и методы класса Outer
  // ...
}

где

  • Outer – имя класса, который содержит в своем теле объявление другого класса с именем Inner;
  • Inner – имя класса, который объявляется в классе Outer.

Классы Outer и Inner могут содержать различные спецификаторы, которые определяют доступ (private, protected, public) или другие свойства класса (static, sealed и т.д.).

 

2. Как выглядит общая форма объявления объекта вложенного класса?

Объект вложенного класса можно объявить в случае, когда вложенный класс объявлен как видимый. Это значит, что видимый вложенный класс должен быть объявлен с любым модификатором доступа кроме private.

Если вложенный класс объявлен как не private-класс, то создание экземпляра этого класса имеет следующий вид:

Outer.Inner objInner = new Outer.Inner();

где

  • Outer – имя внешнего класса, в котором объявляется вложенный класс Inner;
  • Inner – имя вложенного класса, который объявлен в пределах фигурных скобок класса Outer;
  • objInner – имя объекта (экземпляра) класса, который создается;
  • Outer.Inner() – имя конструктора по умолчанию, который вызывается для создания объекта класса. Если в классе Inner реализованы другие параметризированные конструкторы, то этот вызов может быть другим.

 

3. Какие модификаторы доступа могут применяться к вложенным классам?

К вложенным классам могут применяться точно такие же модификаторы доступа как и к обычным – невложенным классам:

  • private. В этом случае вложенный класс есть видимым в пределах фигурных скобок { } внешнего класса;
  • public. В этом случае вложенный класс доступен в пределах внешнего класса, из экземпляра внешнего класса, из унаследованного класса а также за пределами сборки;
  • protected. В этом случае класс есть доступен в пределах внешнего класса а также из методов унаследованных классов;
  • internal. Вложенный класс есть доступен в пределах сборки и недоступен за пределами сборки;
  • protected internal. Вложенный класс может быть доступен из методов внешнего класса, методов унаследованных классов или недоступен из методов за пределами текущей сборки.

Действие модификаторов точно такое же как и в случае с членами данных (методами) класса.

 

4. Пример, который демонстрирует использование классов с различными модификаторами доступа

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

Объявляется класс Outer, который содержит:

  • две внутренние public-переменные с именами d и sd. Переменная sd объявлена как статическая;
  • внутренний метод GetInner1(), демонстрирующий доступ к private-классу Inner1;
  • вложенный класс Inner1, который объявлен как private;
  • вложенный класс Inner2, который объявлен как public;
  • вложенный класс Inner3, который объявлен как internal;
  • вложенный класс Inner4, который объявлен как protected;
  • вложенный класс Inner5, который объявлен как protected internal.

В любом из вложенных классов объявляются:

  • одна нестатическая переменная целого типа;
  • одна статическая переменная целого типа.

Листинг класса Outer следующий:

// класс Outer содержит 5 вложенных классов
public class Outer
{
  // внутренние переменные класса Outer
  public int d;
  static public int sd;

  // доступ к private-классу Inner1 из внутреннего метода класса
  public Inner1 GetInner1()
  {
    Inner1 i1 = new Inner1(); // создать экземпляр класса Inner1

    // доступ к члену данных класса Inner1 через экземпляр класса
    i1.d1 = 25;

    // доступ к статическому члену вложенного класса Inner1
    Inner1.sd1 = 30;

    return i1;
  }

  // private-вложенный класс Inner1
  private class Inner1
  {
    public int d1;
    public static int sd1;
  }

  // public-вложенный класс Inner2
  public class Inner2
  {
    public int d2;
    public static int sd2;
  }

  // internal-вложенный класс Inner3
  internal class Inner3
  {
    public int d3;
    public static int sd3;
  }

  // protected-вложенный класс Inner4
  protected class Inner4
  {
    public int d4;
    public static int sd4;
  }

  // protected-internal вложенный класс Inner5
  protected internal class Inner5
  {
    public int d5;
    public static int sd5;
  }
}

Использование вложенных классов в некотором методе может быть следующим:

// Использование вложенных классов Outer.Inner1, Outer.Inner2, Outer
// 1. Объявить объект класса Outer
Outer o = new Outer();
o.d = 300; // доступ к внутренней переменной через экземпляр класса Outer
Outer.sd = 230; // доступ к статической переменной

// 2. Нет доступа к private-классу Inner1 через экземпляр класса Outer
// Outer.Inner1 i1; - ошибка, класс Inner1 объявлен как private

// 3. Объявить объект public-класса Inner2
Outer.Inner2 i2 = new Outer.Inner2();
i2.d2 = 440;
Outer.Inner2.sd2 = 500; // доступ к статической переменной

// 4. Объявить объект internal-класса Inner3
Outer.Inner3 i3 = new Outer.Inner3();
i3.d3 = 100;
Outer.Inner3.sd3 = 400; // доступ к статической переменной

// 5. Объявить объект protected-класса можно только из унаследованных классов
// Outer.Inner4 i4; - ошибка

// 6. Объявить объект protected-internal-класса можно
Outer.Inner5 i5 = new Outer.Inner5();
i5.d5 = 200;
Outer.Inner5.sd5 = -100;

Как видно из вышеприведенного кода, создавать объекты можно только для классов Inner2, Inner3, Inner5. Чтобы создать объект protected-класса Inner4, нужно объявить другой класс, который наследует класс Outer, например:

// класс Outer2 есть унаследованным от класса Outer
class Outer2 : Outer
{
  // в методе унаследованного класса есть доступ к protected-классу Inner4
  void SomeMethod()
  {
    // создать экземпляр класса Outer.Inner4
    Inner4 i4 = new Inner4(); // работает
    i4.d4 = 23; // доступ через экземпляр класса
    Inner4.sd4 = 330; // доступ к статической переменной
  }
}

Данный пример также показывает, что вложенный private-класс скрывает доступ к объявленной в нем статической переменной из методов других классов. Так же, скрывает доступ и вложенный protected-класс.

 

5. Объявление и использование статического вложенного класса в нестатическом. Пример

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

Пример. Объявляется класс Outer, содержащий объявление вложенного статического (static) класса Inner. В классе Inner объявляется статическая внутренняя public-переменная. Текст класса Outer следующий:

// класс Outer - нестатический
public class Outer
{
  // внутренние переменные класса Outer
  public int d;
  static public int sd;

  // статический вложенный класс Inner
  public static class Inner
  {
    // только статические переменные могут объявляться в статическом классе
    public static int sd; // статическая внутренняя переменная класса Inner
  }
}

Использование статического вложенного класса может быть приблизительно таким:

// доступ к статической переменной статического класса Outer.Inner
Outer.Inner.sd = 45;

// создать объект (экземпляр) класса Outer
Outer o = new Outer();
o.d = 30; // есть доступ к переменным экземпляра класса через объект
Outer.sd = 102; // доступ к статической переменной класса Outer

// создавать объект статического класса нельзя
//Outer.Inner i = new Outer.Inner(); - это ошибка!

 

6. Можно ли в статическом классе объявить нестатический вложенный класс?

Да, можно. В статическом классе можно объявлять нестатические вложенные классы. Однако, в статическом классе нельзя объявлять нестатические переменные и методы.

Более подробно об использовании статических переменных, методов, классов описывается в теме:

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

// класс Outer - статический
public static class Outer
{
  // внутренние переменные класса Outer
  // только статические экземпляры можно объявлять в статическом классе
  // public int d; - ошибка!
  static public int sd;

  // нестатический вложенный класс Inner - может объявляться в статическом классе
  public class Inner
  {
    public int d; // нестатическая переменная
    public static int sd; // статическая внутренняя переменная класса Inner
  }
}

Использование классов Outer и Outer.Inner может быть, например, таким:

// использование нестатического класса в статическом классе
// доступ к статической переменной sd класса Outer.Inner
Outer.Inner.sd = 230;

// доступ к статической переменной sd класса Outer
Outer.sd = 132;

// Нельзя создавать экземпляр (объект) статического класса
// Outer o = new Outer(); // ошибка, поскольку Outer - статический класс

// создать экземпляр вложенного класса Outer.Inner
Outer.Inner i = new Outer.Inner();
і.d = 323; // доступ к нестатической переменной d класса Outer.Inner

 

7. Пример объявления и использования статического вложенного класса в другом статическом классе

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

Пусть заданы объявления статических классов Outer и Inner:

// класс Outer - статический
public static class Outer
{
  // только статические экземпляры можно объявлять в статическом классе
  static public int sd;

  // статический вложенный класс Inner - может объявляться в статическом классе
  public static class Inner
  {
    // здесь только статические элементы
    public static int sd; // статическая внутренняя переменная класса Inner
  }
}

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

// использование статического класса в статическом классе
// доступ к статической переменной sd класса Outer.Inner
Outer.Inner.sd = 140;

// доступ к статической переменной sd класса Outer
Outer.sd = 110;

// Нельзя создавать экземпляр (объект) статического класса
// Outer o = new Outer(); // ошибка, поскольку Outer - статический класс

 


Связанные темы