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;
…
}
Третий принцип: поддержка полиморфизма в C#
Теперь давайте рассмотрим заключительный принцип ООП – полиморфизм. Напомним, что базовый класс Employee определил метод GiveBonus(), который был реализован так.
// Предоставление премий работникам.
public class Employee {
…
public void GiveBonus(float amount) { currPay += amount;}
}
Ввиду того, что этот метод является открытым, вы теперь имеете возможность выдать премии продавцам и менеджерам (а также продавцам, занятым неполный рабочий день).
static void Main(string[] args) {
// Премии работникам.
Manager chucky = new Manager("Сhucky", 50, 92, 100000, "333-23-2322", 9000);
chucky. GiveBonus(300);
chucky.DisplayStats();
SalesPerson fran = new SalesPerson("Fran", 43, 93, 3000, "932-32 - 3232 " , 31);
fran. GiveBonus(200); fran.DisplayStats();
Console.ReadLine();
}
Недостаток данного варианта в том, что наследуемый метод GiveBonus() действует одинаково для всех подклассов. В идеале премия продавца, как и продавца, работающего на неполную ставку, должна зависеть от числа продаж. Возможно, менеджеры должны получать льготы в дополнение к денежному вознаграждению, В связи с этим возникает интересный вопрос: "Каким образом родственные объекты могут по-разному реагировать на одинаковые запросы?"
Ключевые слова virtual и override
Полиморфизм обеспечивает подклассам возможность задать собственную реализацию методов, определенных базовым классом. Чтобы соответствующим образом изменить наш проект, мы должны рассмотреть применение ключевых слов C# virtual и override. Если в базовом классе нужно определить метод, допускающий переопределение подклассом, то этот метод должен быть виртуальным.
Читать дальше