Рис. 3.4. Простая логика конструктора
Замечание. После определения пользовательского конструктора для типа класса конструктор, заданный по умолчанию, будет удален. Чтобы в этом случае у пользователей объекта осталась возможность создавать экземпляры типа с помощью конструктора, заданного по умолчанию такой конструктор нужно явно переопределить, как это сделано в предыдущем примере.
Если вы имеете опыт программирования на языке C++, то у вас в связи с предыдущими примерами программного кода могут возникать вопросы. В частности, следует обратить внимание на то, что метод Main() типа HelloClass не имеет явных операторов уничтожений ссылок c1 и с2.
Это не ужасное упущение, а правило .NET. Как и программистам Visual Basic и Java, программистам C# не требуется уничтожать управляемые объекты явно. Механизм сборки мусора .NET освобождает память автоматически, поэтому в C# не поддерживается ключевое слово delete. В главе 5 процесс сборки мусора будет рассмотрен подробно. До того времени вам достаточно знать лишь о том, что среда выполнения .NET автоматически уничтожит размещенные вами управляемые объекты.
Определение "объекта приложения"
В настоящее время тип HelloClass решает две задачи. Во-первых, этот класс определяет точку входа в приложение (метод Main()). Во-вторых, HelloClass поддерживает элемент данных и несколько конструкторов. Все это хорошо и синтаксически правильно, но немного странным может показаться то, что статический метод Main() создает экземпляр того же класса, в котором этот метод определен.
class HelloClass {
…
public static int Main(string[] args) {
HelloClass c1 = new HelloClass();
…
}
}
Такой подход здесь и в других примерах используется только для того, чтобы сосредоточиться на иллюстрации решения соответствующей задачи. Более естественным подходом была бы факторизация типа HelloClass с разделением его на два отдельных класса: HelloClass и HelloApp. При компоновке C#-приложения обычно один тип используется в качестве "объекта приложения" (это тип, определяющий метод Main()), в то время как остальные типы и составляют собственно приложение.
В терминах ООП это называется разграничение обязанностей. В сущности, этот принцип проектирования программ требует, чтобы класс отвечал за наименьший объем работы. Поэтому мы можем изменить нашу программу следующим образом (обратите внимание на то, что здесь в класс HelloClass добавляется новый член PrintMessage()).
class HelloClass {
public string userMessage;
public HelloClass() {Console.WriteLine("Вызван конструктор, заданный по умолчанию!");}
public HelloClass(string msg) {
Console.WriteLine("Вызван пользовательский конструктор!");
userMessage = msg;
}
public void PrintMessage() {
Console.WriteLine("Значение userMessage: {0}\n", userMessage);
}
}
class HelloApp {
public static int Main(string[] args) {
HelloClass c1 = new HelloClass("Эй, вы, там…");
c1.PrintMessage();
}
}
Исходный код.Проект HelloClass размещен в подкаталоге, соответствующем главе 3.
Многие примеры приложений, созданные для первых глав этой книги, используют класс System.Console. Конечно, интерфейс CUI (Console User Interface – консольный интерфейс пользователя) не так "соблазнителен", как интерфейс Windows или WebUI, но, ограничившись в первых примерах интерфейсом CUI, мы можем сосредоточиться на иллюстрируемых базовых понятиях, не отвлекаясь на сложности построения GUI (Graphical User Interface – графический интерфейс пользователя).
Как следует из его имени, класс Console инкапсулирует элементы обработки потоков ввода, вывода и сообщений об ошибках для консольных приложений. С выходом .NET 2.0 тип Console получил новые функциональные возможности.
В табл. 3.2 представлен список некоторых наиболее интересных из них (но, конечно же, не всех).
Таблица 3.2.Подборка членов System.Console, новых для .NET 2.0
Член |
Описание |
BackgroundColor ForegroundColor |
Свойства, устанавливающие цвет изображения/фона для текущего потока вывода. Могут получать значения из перечня ConsoleColor |
BufferHeight BufferWidth |
Свойства, контролирующие высоту/ширину буферной области консоли |
Clear() |
Метод, выполняющий очистку буфера и области отображения консоли |
Title |
Свойство, устанавливающее заголовок текущей консоли |
WindowHeight WindowWidth WindowTop WindowLeft |
Свойства, контролирующие размеры консоли относительно заданного буфера |
Ввод и вывод в классе Console
Читать дальше