Вложенные определения типов
Вложенные определения типов
Перед тем как рассмотреть заключительный принцип ООП (полиморфизм), давайте обсудим технику программирования, называемую вложением типов. В C# можно определить тип (перечень, класс, интерфейс, структуру или делегат) в пределах области видимости класса или структуры. При этом вложенный ("внутренний") тип считается членом содержащего его ("внешнего") класса, с точки зрения среды выполнения ничем не отличающимся от любого другого члена (поля, свойства, метода, события и т.п.). Синтаксис, используемый для вложения типа, исключительно прост.
public class OuterClass {
// Открытый вложенный тип могут использовать все.
public class PublicInnerClass{}
// Приватный вложенный тип могут использовать только члены
// содержащего его класса.
private class PrivateInnerClass{}
}
Синтаксис здесь ясен, но понять, почему вы можете это делать, не так просто. Чтобы прийти к пониманию этого подхода, подумайте над следующим.
• Вложение типов подобно их композиции ("has-a"), за исключением того, что вы имеете полный контроль над доступом на уровне внутреннего типа, а не содержащегося объекта.
• Ввиду того, что вложенный тип является членом класса-контейнера, этот тип может иметь доступ к приватным членам данного класса.
• Часто вложенный тип играет роль вспомогательного элемента для класса-контейнера, и его использование "внешним миром" не предполагается.
Когда некоторый тип содержит другой тип класса, он может создавать члены-переменные вложенного типа, точно так же, как для любого другого своего элемента данных. Но если вы пытаетесь использовать вложенный тип из-за границ внешнего типа, вы должны уточнить область видимости вложенного типа, указав его абсолютное имя. Изучите следующий пример программного кода.
static void Main (string[] args) {
// Создание и использование открытого внутреннего класса. Все ОК!
OuterClass.PublicInnerClass inner;
inner = new OuterClass.PublicInnerClass();
// Ошибка компиляции! Нет доступа к приватному классу.
OuterClass.PrivateInnerClass inner2;
inner2 = new OuterClass.PrivateInnerClass();
}
Чтобы использовать этот подход в нашем примере, предположим, что мы вложили BenefitPackage непосредственно в тип класса Employee.
// Вложение BenefitPackage.
public class Employee {
...
public class BenefitPackage {
public double ComputePayDeduction() {return 125.0;}
}
}
Глубина вложения может быть любой. Предположим, что мы хотим создать перечень BenefitPackageLevel, указывающий различные уровни льгот, которые может выбрать работник. Чтобы программно реализовать связь между Employee, BenefitPackage и BenefitPackageLevel, можно вложить перечень так, как показано ниже.
// Employee содержит BenefitPackage.
public class Employee {
// BenefitPackage содержит BenefitPackageLevel.
public class BenefitPackage {
public double ComputePayDeduction() {return 125.0;}
public enum BenefitPackageLevel {
Standard, Gold, Platinum
}
}
}
С учетом отношений вложении обратите внимание на то, как приходится иcпользовать этот перечень.
Static void Main(string[] args) {
// Создание переменной BenefitPackageLevel.
Employee.BenefitPackage.BenefitPackageLevel myBenefitLevel = Employee.BenefitPackage.BenefitPackageLevel.Platinum;
…
}