Смекни!
smekni.com

Основы алгоритмизации и программирования 2 (стр. 22 из 32)

Использовавшиеся методы Console.WriteLine() и Convert.ToString() являются статическими. Ни в какой момент времени от нас не требуется создавать экземпляры классов Console или Convert (более того, даже если попытаься это сделать, то все равно ничего бы не получилось, поскольку к конструкторам этих классов не существует общего доступа, что обсуждалось ранее).

Существуют различные ситуации, при которых статические свойства и методы могут быть использованы с большой пользой.

В синтаксисе UML статические члены классов выделяются подчеркиванием (см. рис. 6.5).

5.3.Ссылочные и значимые типы данных

Все данные в С# хранятся в переменных двумя способами, которые определяются типом переменной. Этот тип может относиться к одной из двух категорий: либо ссылочный тип, либо значимый. Вот в чем состоит различие между ними:

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

На самом деле при использовании С# это не должно нас особенно беспокоить. До настоящего момента мы использовали переменные типа string (которые относятся к ссылочному типу) и другие простые переменные (большинство из которых относится к значимому типу, например, int) практически одинаково.

Среди простых типов ссылочными являются только string и object, хотя массивы также неявно представляют собой ссылочный тип. Каждый создаваемый нами класс будет относиться к ссылочному типу – именно поэтому мы и остановились на этом моменте.

5.3.1.Структуры

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

Тот факт, что структурные типы и классы похожи друг на друга, возможно, стал вам ясен давно, особенно после того, как в главе 6 было сказано, что в структурных типах могут использоваться функции. Этот вопрос более подробно будет рассматриваться в следующей главе.

5.3.2.ООП в приложениях Windows

ПРАКТИКУМ: объекты в действии

1. Создайте новое приложение Windows.

2. Добавьте в приложение новое средство управления Button с помощью панели Toolbox и разместите его в центре Form1, как показано на рисунке слева.

3. Дважды щелкните по кнопке мышью для того, чтобы добавить код, предназначенный для обработки нажатия кнопки мыши. Внесите изменения в появившийся код, как показано ниже: /// <summary>

/// The main entry point for the application.

/// </summary> [STAThread]

static void Main()

{

Application.Run(new Forml()); }

private void buttonl_Click(object sender, System.EventArgs e) {

( (Button)sender).Text = "Clicked!"; Button newButton = new Button(); newButton. Text = "NewButton!";

newButton. Click += new EventHandler(newButton_Click); Controls.Add(newButton); }

private void newButton_Click(object sender, System.EventArgs e) {

((Button)sender).Text = "Clicked!!"; } } }

4. Запустите приложение.

5. Щелкните мышью по кнопке с надписью button1.

6. Щелкните мышью по кнопке с надписью New Button!.

Как это работает

Написав всего несколько строк кода, мы создали Windows-приложение, которое выполняет некоторые действия, одновременно иллюстрируя использование определенных методов ООП в С#. Фраза "объектом может быть все, что угодно" становится еще более справедливой, когда дело касается Windows-приложений. Начиная от формы, в которой это выполняется, и заканчивая средствами управления в этой форме, нам постоянно приходится пользоваться методами ООП. В процессе описания этого примера автор выделил некоторые понятия; это сделано для того, чтобы уяснить их соотношение друг с другом.

Первое, что мы сделали в нашем приложении,– добавили в форму Form1 новую кнопку. Она представляет собой объект, называемый Button. Далее, щелкнув два раза мышью, мы добавили обработчик событий, который ожидает наступления события click (нажатие), генерируемого объектом Button. Этот обработчик событий добавляется в код объекта Form, где инкапсулировано приложение, в качестве частного метода:

private void buttonl_Click(object sender, System.EventArgs e) {…} В качестве описателя используется ключевое слово private.

Первая строка кода из числа добавленных нами изменяет текст на нажимаемой кнопке. В этом случае используется полиморфизм, с которым мы уже сталкивались. Объект Button, представляющий нажатую нами кнопку, передается обработчику событий как параметр типа object, тип которого мы изменяем на тип Button (это оказывается возможным, поскольку объект Button наследуется от класса .NET System.Object, для которого object является синонимом). Далее мы изменяем свойство объекта Text, чтобы изменить выводящийся текст:

((Button)sender).Text = "Clicked!";

Затем мы создаем новый объект Button с помощью ключевого слова new (обратите внимание, что в этом примере пространства имен заданы так, что позволяют использовать простой синтаксис, в противном случае нам бы пришлось вводить полностью квалифицированное имя объекта – System.Windows.Forms.Button): Button newButton = new Button(); newButton.Text = "NewButton!";

Затем в произвольное место программы добавляется обработчик событий, который будет использоваться для того, чтобы отреагировать на событие click, генерируемое новой кнопкой: private void newButton_Click(object sender, System.EventArgs e) {

((Button)sender).Text = "Clicked!!"; }

Затем мы регистрируем данный обработчик событий как ожидающий наступления события Click с помощью некоторого синтаксиса перегрузки оператора. Одновременно мы создаем новый объект EventHandler, используя для этого конструктор не по умолчанию, с именем новой функции обработчика событий:

newButton.Click += new EventHandler(newButton_Click);

В заключение мы используем объект из семейства controls данной формы для того, чтобы добавить в форму новую кнопку с помощью метода Add(): Controls.Add(newButton);

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

5.4. Вопросы для повторения

1. Принципы ООП.

2. Понятие объекта.

3. Понятие свойств и полей.

4. Понятие методов.

5. Жизненный цикл объекта.

6. Конструкторы и деструкторы.

7. Статические члены класса.

8. Ссылочные и значимые типы данных.

6. ОПРЕДЕЛЕНИЕ КЛАССОВ

6.1.Определение классов в С#

В языке С# для описания классов используется ключевое слово class При этом необходимо задействовать следующую основную конструкцию

class myClass {// члены класса }

Этот код определяет класс с именем myClass. После того как мы определили класс, мы вольны создавать экземпляры этого класса в нашем проекте везде, где имеется доступ к этому определению. По умолчанию классы определяются как internal (внутренние), что означает, что доступ к ним будет иметь только код текущего проекта. Мы можем указать это явно, воспользовавшись ключевым словом определения доступа internal (хотя и не обязаны этого делать):

internal class MyClass { // члены класса }

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

public class MyClass { // члены класса }

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

Кроме ключевых слов этих двух модификаторов доступа, для описания класса можно использовать ключевое слово abstract (абстрактный; создавать экземпляры такого класса запрещено, он может только наследоваться, в нем допускается наличие абстрактных членов) или sealed (изолированный, такой класс не может наследоваться). Эти ключевые слова являются взаимоисключающими Таким образом, абстрактный класс должен определяться следующим образом.

public abstract class MyClass {

// члены класса, среди которых могут быть абстрактные }

В данном случае MyClass является общим абстрактным классом, хотя также возможны и внутренние абстрактные классы.

Изолированные классы определяются следующим образом public sealed class MyClass { // члены класса }

Так же, как абстрактные классы, изолированные классы могут быть общими или внутренними.

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

public class MyClass : MyBase { // члены класса }

Заметьте, что в определении класса в С# допускается наличие только одного базового класса, и если данный класс наследуется от некоторого абстрактного класса, то в нем должны быть реализованы все наследуемые абстрактные члены (если, конечно, этот класс сам не является абстрактным).

Компилятор не допустит ситуации, при которой производный класс будет более доступным, чем его базовый класс. Отсюда следует, что внутренний класс может наследоваться от общего базового класса, но общий класс не может наследоваться от внутреннего базового класса. Следующий код является допустимым:

public class MyBase {

// члены класса } internal class MyClass : МуВаsе {

// члены класса }

А такой код не пройдет компиляцию:

internа1 class MyBase {

// члены класса } public class MyClass : MyBase { // члены класса }

Если базовый класс не задан, то класс наследуется только от базового класса System.Object (для которого в С# используется синоним object). System.Object безусловно является корневым в иерархии наследования для всех классов. Мы будем изучать этот фундаментальный класс ниже.