Классы, член данные и член функции класса

Министерство образования и науки Российской Федерации

КАЗАНСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

Им.А.Н.Туполева

Р. Р. Вафин В.И Медведев

Методические указания к лабораторным работам

По объектно-ориентированному программированию

Учебное пособие

Казань 2008

Министерство образования и науки Российской Федерации

КАЗАНСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

им.А.Н.Туполева

Р.Р.Вафин, В.И.Медведев

Методические указания к лабораторным работам

По объектно-ориентированному программированию

Учебное пособие

Рекомендовано к изданию Учебно-методическим центром

КГТУ им.А.Н.Туполева

Казань 2008

УДК 681.3

Р. Р.Вафин, В.И.Медведев.: Лабораторный практикум по объектно-ориентированному программированию: Учебное пособие. Казань: Изд-во Казан. Гос. техн. Ун-та, 2008. 100 с.

ISBN

Рассматриваются вопросы основ теории объектно-ориентированного программирования с использованием языка программирования Visual C#.NET. Приводятся примеры объектно-ориентированного программирования на языке Visual C#.NET.

Табл. 1. ил. 5. Библиогр.: 3 назв.

Рецензенты:

ISBN © Изд-во Казан. гос. техн. ун-та, 2008

© Р. Р.Вафин, В.И.Медведев 2008

Лабораторная работа №1

Структура консольного приложения.

Консольный ввод - вывод

Язык программирования C# является прямым наследником языка С++. Он унаследовал многие синтаксические конструкции языка С и объектно-ориентированную модель С++. В отличие от С++ С# является чисто объектно-ориентированным языком. В объектно-ориентированном программировании ход выполнения программы определяется объектами. Объекты это экземпляры класса. Класс это абстрактный тип данных, определяемый пользователем (программистом). Класс включает в себя данные и функции для обработки этих данных. В С# запрещены глобальные функции. Все функции должны быть обязательно определены внутри класса. Не является исключением и главная функция языка С# Main( ) (в отличии от языка С пишется с прописной буквы).

Объявление класса синтаксически имеет следующий вид:

сlass имя_класса

{

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

}

Члены класса это данные и функции для работы с этими данными. Не затрагивая пока определения членов класса, рассмотрим общую структуру приложения для консоли. Для этого создадим пустой проект в интегрированной рабочей среде Microsoft Visual Studio.NET и проанализируем, что подготовит нам мастер приложения. Запустим на выполнение среду Microsoft Visual Studio.NET через кнопку «Пуск» панели задач. В открывшемся окне выберем пункт File|New|Project. В диалоговом окне New Project необходимо выбрать тип проекта Visual C# Projects и шаблон приложения - Console Application. В поле наименование (Name) ввести новое имя проекта, либо согласиться с именем, которое предлагает мастер. В поле местоположение (Location) выбрать или ввести полный путь к рабочей папке проекта, например:

C:\work\4255

и затем щелкнуть мышкой на кнопке ОК.

При этом появится шаблон приложения, подготовленный для нас мастером:

using System;

namespace ConsoleApplication10

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class Class1

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

//

// TODO: Add code to start application here

//

}

}

}

Первая строчка проекта using System;, включает в себя директиву using, которая сообщает компилятору, где он должен искать классы (типы), не определенные в данном пространстве имен. Мастер, по умолчанию, указывает стандартное пространство имен System, где определена большая часть типов среды .NET.

Следующей строчкой namespace ConsoleApplication10 мастер предложения определяет пространство имен для нашего приложения. По умолчанию в качестве имени выбирается имя проекта. Область действия пространства имен определяется блоком кода, заключенного между открывающей и закрывающей фигурными скобками. Пространство имен обеспечивает способ хранения одного набора имен отдельно от другого.

Имена, объявленные в одном пространстве имен не конфликтуют, при совпадении, с именами, объявленными в другом пространстве имен.

В шаблоне приложения имеется множество строк, которые являются комментариями.

В C# определены три вида комментариев:

- многострочный (/*…*/)

- однострочный (//…)

- XML (///) – комментарий для поддержки возможности создания самодокументированного кода.

Строчка [STAThread] является атрибутом. Атрибуты задаются в квадратных скобках. С помощью атрибута в программу добавляется дополнительная описательная информация, связанная с элементом кода, непосредственно перед которым задается атрибут. В нашем случае указывается однопоточная модель выполнения функции Main.

Заголовок функции:

static void Main(string[] args)

Функция Main определена как статическая (static) с типом возвращаемого значения void. Функция Main( ) C# как и функция main( ) языка С может принимать аргументы. Аргумент - это строковый массив, содержащий элементы командной строки. Тело функции пустое и в нем содержится, в виде комментария, предложение добавить туда код для запуска приложения:

// TODO: Add code to start application here

Воспользуемся этим предложением и добавим в тело функции одну строчку:

static void Main(string[] args)

{

//

// TODO: Add code to start application here

Console.WriteLine("Привет!");

//

}

затем, скомпилируем и запустим приложение на выполнение. Для этого необходимо выбрать пункт меню Debug | Start Without Debugging или нажать комбинацию клавиш Ctrl+F5. В результате выполнения программы появится окно со строкой приветствия.

Как вы, наверное, догадались, строка:

Console.WriteLine("Привет!");,

выводит сообщение на консоль.

Функции консольного ввода-вывода являются методами класса Console библиотеки классов среды .NET.

Для ввода строки с клавиатуры используется метод Console.ReadLine(), а для ввода одного символа метод Console.Read().

Для консольного вывода также имеются два метода:

- метод Console.Write(), который выводит параметр, указанный в качестве аргумента этой функции,

- метод Console.WriteLine(),который работает так же, как и Console.Write(), но добавляет символ новой строки в конец выходного текста.

Для анализа работы этих методов модифицируйте функцию Main( ) так, как показано ниже :

static void Main(string[] args)

{

// TODO: Add code to start application here

Console.WriteLine("Введите ваше имя");

string str=Console.ReadLine();

Console.WriteLine("Привет "+str+"!!!");

Console.WriteLine("Введите один символ с клавитуры");

int kod=Console.Read();

char sim=(char)kod;

Console.WriteLine("Код символа "+sim+" = "+kod);

}

Скомпилируйте и выполните приложение.

Проанализируйте код функции Main( ) и результат ее работы.

Здесь хорошо видно, что строку вывода метода Console.WriteLine можно формировать из переменных разного типа, просто объединяя их в одну строку с помощью знака +.

Можно сформировать точно такую же выходную строку, используя другую модификацию метода Console.WriteLine , которая принимает несколько параметров (список параметров), наподобие функции printf() языка программирования Си. Первым параметром списка является строка, содержащая маркеры в фигурных скобках. Маркер это номер параметра в списке. При выводе текста вместо маркеров будут подставлены соответствующие параметры из остального списка.

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

static void Main(string[] args)

{

// TODO: Add code to start application here

Console.WriteLine("Введите ваше имя");

string str=Console.ReadLine();

Console.WriteLine("Привет "+str+"!!!");

Console.WriteLine("Введите один символ с клавитуры");

int kod=Console.Read();

char sim=(char)kod;

Console.WriteLine("Код символа "+sim+" = "+kod);

Console.WriteLine("Код символа {0} = {1}",sim,kod);

}

Скомпилируйте и выполните это приложение. Проанализируйте, полученный результат.

После маркера через запятую можно указать, сколько позиций отводится для вывода значений. Например, запись {1,3} означает, что для печати первого элемента списка отводится поле шириной в три символа. Причем, если значение ширины положительно, то производится выравнивание по правому краю поля, если отрицательно то по левому.

Добавив 4 новые строчки в конец кода функции Main(), убедимся в этом:

static void Main(string[] args)

{

Console.WriteLine("Введите ваше имя");

string str=Console.ReadLine();

Console.WriteLine("Привет "+str+"!!!");

Console.WriteLine("Введите один символ с клавитуры");

int kod=Console.Read();

char sim=(char)kod;

Console.WriteLine("Код символа "+sim+" = "+kod);

Console.WriteLine("Код символа {0} = {1}",sim,kod);

int s1=255;

int s2=32;

Console.WriteLine(" \n{0,5}\n+{1,4}\n-----\n{2,5}",s1,s2,s1+s2);

Console.WriteLine(" \n{1,5}\n+{0,4}\n-----\n{2,5}",s1,s2,s1+s2);

}

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

Существует 8 различных форматов вывода:

С – формат национальной валюты,

D – десятичный формат,

E – научный (экспоненциальный) формат,

F – формат с фиксированной точкой,

G – общий формат,

N – числовой формат,

P – процентный формат,

X – шестнадцатеричный формат

Например, запись {2,9:C2} – означает, что для вывода второго элемента из списка, отводится поле шириной в 9 символов. Элемент выводится в формате денежной единицы с количеством знаков после запятой равной двум. При выводе результата происходит округление до заданной точности.

Для иллюстрации вышесказанного модифицируем функцию Main(), как показано ниже:

static void Main(string[] args)

{

// TODO: Add code to start application here

Console.WriteLine("Введите ваше имя");

string str=Console.ReadLine();

Console.WriteLine("Привет "+str+"!!!");

Console.WriteLine("Введите один символ с клавитуры");

int kod=Console.Read();

char sim=(char)kod;

Console.WriteLine("Код символа "+sim+" = "+kod);

Console.WriteLine("Код символа {0} = {1}",sim,kod);

int s1=255;

int s2=32;

Console.WriteLine(" \n{0,5}\n+{1,4}\n-----\n{2,5}",s1,s2,s1+s2);

Console.WriteLine(" \n{1,5}\n+{0,4}\n-----\n{2,5}",s1,s2,s1+s2);

double sum1=500.3467;

double sum2=43.5;

Console.WriteLine(" \n{0,10:C2}\n+{1,9:C2}\n-----\n{2,10:C2}",

sum1,sum2,sum1+sum2);

}

Скомпилируйте и запустите код на выполнение.

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

Вопросы:

1. Какие статические методы классаConsole, используются для ввода с клавиатуры?

2. Какой тип данных возвращает метод Read()?

3. Какой тип данных возвращает метод ReadLine()?

4. Какие статические методы классаConsole, используются для вывода на консоль?

5. Как можно сформировать строку консольного вывода, используя знак сложения “+”?

6. Что означают числа, заключенные в {…} , форматной строки метода Console.WriteLine("Код символа {0} = {1}",sim,kod);?

7. Можно ли с помощью маркеров в {…} изменить порядок вывода параметров из списка метода Console.WriteLine, не изменяя порядка перечисления параметров в списке?

8. Как можно задать ширину поля вывода в символах?

9. Как можно организовать консольный вывод, выровненный по левому или по правому краю поля?

10. Как организовать вывод в шестнадцатеричном формате? Какие другие форматы вы знаете?

11. Как организовать вывод в формате с фиксированной точкой с точностью до трех знаков после запятой с округлением?

Задания:

Вывести на консоль значения функции в диапазоне углов от 0 до 180 градусов с шагом в 10 градусов. Для расчета использовать статические функции библиотечного класса Math. Вывод организовать в виде таблицы, состоящей из столбцов, выровненных по правому краю:

Первый столбец – значение аргумента функции в градусах, ширина поля вывода 4 символа.

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

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

1. F(x)=sin(x);

2. F(x)=cos(x);

3. F(x)= sin(x)+cos(x);

4. F(x)= tg(x);

5. F(x)=ctg(x);

6. F(x)=sinh(x);

7. F(x)=cosh(x);

8. F(x)= sinh(x)+cosh(x);

9. F(x)= tgh(x);

10. F(x)=ctgh(x);

Лабораторная работа №2

Классы, член данные и член функции класса

Класс это абстрактный тип данных, определяемый программистом (пользователем).

С помощью классов определяются свойства объектов. Объекты это экземпляры класса.

Объявление класса синтаксически имеет следующий вид:

сlass имя_класса

{

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

}

Члены класса – это данные и функции для работы с этими данными.

Имя класса – это, по сути дела, имя нового типа данных.

Создание экземпляра (объекта) класса осуществляется с помощью оператора new:

Имя_класса имя_объекта = new имя_класса();

Доступ к членам класса управляем. Управление доступом осуществляется с помощью спецификаций доступа:

- public – общедоступный член класса.

- private – член класса доступен только внутри данного класса.

- protected – член класса доступен только внутри данного класса и внутри классов, производных от данного.

- internal – член класса доступен только внутри данной сборки.

По умолчанию в классе устанавливается спецификация доступа private. Спецификация доступа, отличная от private, должна указываться явно перед каждым членом класса.

Данные класса подразделяются на поля, константы и события.

Поле – это обычная член-переменная, содержащая некоторое значение.

Можно, например, объявить класс, членами которого являются только поля:

class CA

{

public int x;

protected float z;

double m;

public char sim;

private decimal sum;

}

Обратите внимание, на то, что поле m здесь объявлено по умолчанию приватным.

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

public const int x = 25;

События это члены класса, предназначенные для информирования клиентов класса, что что-то произошло. В данной лабораторной работе события рассматриваться не будут.

Все не статические член функции класса имеют неограниченный доступ ко всем член данным класса независимо от спецификации доступа.

Методы

В основном, с помощью методов класса осуществляется обработка член данных класса. Другими словами, методы определяют поведение экземпляров данного класса. Методы класса это обычные функции С - стиля.

В отличии от функций С, при передаче методу параметров по ссылке, необходимо указывать ключевое слово refили out. Эти ключевые слова сообщают компилятору, что адреса параметров функции совпадают с адресами переменных, передаваемых в качестве параметров. Любое изменение значения параметров в этом случае приведет к изменению и переменных вызывающего кода. Рекомендуется для входного параметра использовать ключевое слово ref,а для выходного параметра ключевое словоout, так какпараметр функции с ключевым словом ref должен быть обязательно проинициализирован перед вызовом функции. При вызове методов указание ключевых слов refи out обязательно. Методы могут быть объявлены с ключевым словом static например:

public static int minabs(ref int x,ref int y)

{

//тело функции

}

В этом случае для вызова метода указывается имя класса, в котором она определена, и через точку имя метода:

Cmin.minabs(ref a,ref b);

Точка в С# означает принадлежность функции данному классу (в нашем случае Cmin).

Для закрепления изложенного материала создайте проект для консоли, введите текст приложения из примера 1.

Скомпилируйте и проанализируйте результаты работы приложения.

Пример 1:

using System;

namespace ConsoleApplication12

{

class Cmin

{

public static int min(int x,int y)

{

int z = (x<y)?x:y;

return z;

}

public static int minabs(ref int x,ref int y)

{

x = (x<0)?-x:x;

y = (y<0)?-y:y;

int z = (x<y)?x:y;

return z;

}

}

class Class1

{

[STAThread]

static void Main(string[] args)

{

int a=-4;

int b=2;

Console.WriteLine("a={0} b={1}",a,b);

int k =Cmin.min(a,b);

Console.WriteLine("a={0} b={1}",a,b);

Console.WriteLine("k="+k);

k =Cmin.minabs(ref a,ref b);

Console.WriteLine("a={0} b={1}",a,b);

Console.WriteLine("k="+k);

}

}

}

Свойства

Свойства в С# состоят из объявления поля и методов-аксессоров для работы с этим полем.

Эти методы- аксессоры называются получатель (get) и установщик (set).

Например, простейшее свойство y, работающее с полем m, можно представить следующим образом:

private int m=35;

public int y

{

get

{

return m;

}

set

{

m=value;

}

}

Свойство, определяется, так же как и поле, но после имени свойства идет блок кода, включающий в себя два метода get и set. Код этих методов может быть сколь угодно сложным, но в нашем случае это всего лишь один оператор. Аксессор get всегда возвращает значение того типа, который указан в определении свойства. Аксессор set всегда принимает в качестве параметра переменную value, которая передается ему неявно. Один из аксессоров может быть опущен, в этом случае мы получаем поле только для чтения или только для записи.

Обращение к свойству осуществляется точно так же как и к полю.

Пример 2:

using System;

namespace ConsoleApplication11

{

class CStatic

{

private int m=35;

public int y

{

get

{

return m;

}

set

{

m=value;

}

}

}

class Class1

{

[STAThread]

static void Main(string[] args)

{

// TODO: Add code to start application here

CStatic p=new CStatic();//создается экземпляр класса

Console.WriteLine("{0}",p.y);

p.y=75;

int z = p.y;

Console.WriteLine("{0}",z);

}

}

}

Введите текст программы из примера 2, скомпилируйте и проанализируйте работу приложения.

Индексаторы

Индексаторы позволяют приложению обращаться с объектом класса так, как будто он является массивом. Индексатор во многом напоминает свойство, но в отличие от свойства он принимает в качестве параметра индекс массива. Так как объект класса используется как массив, то в качестве имени класса используется ключевое слово this.

Пример 3:

using System;

namespace ConsoleApplication13

{

class Rmas

{

protected float[] msf=new float[10];

public float this[int j]

{

get

{

return msf[j];

}

set

{

msf[j]=value;

}

}

}

class Class1

{

static void Main(string[] args)

{

Rmas obj = new Rmas();

for(int i=0; i<10;i++)

{

obj[i] = (float)1.5*i;

}

for(int i=0; i<10;i++)

{

Console.WriteLine("{0}",obj[i]);

}

}

}

}

Вопросы:

1. Как объявляется класс?

2. Разрешается ли в объявлении структуры и класса инициализировать их член – данные?

3. Какие спецификации используются в классе и структуре для управления доступом к членам класса?

4. Чем отличаются по своему действию спецификации private от protected?

5. Какая спецификация доступа к данным устанавливается по умолчанию, при объявлении класса?

6. Какая спецификация доступа к данным устанавливается по умолчанию, при объявлении структуры?

7. Чем отличается передача параметров методам с помощью модификатора ref от передачи параметров методам с помощью модификатора out?

8. Чем отличается обращение к статическим методам класса от обращения к не статическим методам?

9. Что такое свойство?

10. Сколько свойств может быть объявлено в классе?

11. Может ли свойство использоваться для работы сразу с несколькими полями?

12. Сколько индексаторов может быть объявлено в классе для работы, например, с одномерными массивами?

13. Почему индексаторы называют интеллектуальными массивами?

Задания:

1. Введите текст программ из примеров 1,2.3, скомпилируйте и проанализируйте работу приложений.

2. Объявить класс, содержащий два поля целого типа, свойства для работы с этими полями, а также статическую функцию. Функция принимает два параметра целого типа и осуществляет обмен значений этих параметров. Создать объект этого класса. Ввести с клавиатуры два числа и присвоить значения этих чисел полям объекта. Распечатать поля объекта. Осуществить обмен значений полей объекта и вновь распечатать поля объекта.

3. Объявить класс, содержащий два поля целого типа, свойства для работы с этими полями, а также функцию. Функция возвращает сумму значений полей класса. Создать объект этого класса. Ввести с клавиатуры два числа и присвоить значения этих чисел полям объекта. Распечатать поля объекта и их сумму.

4. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом, а также функцию, для определения минимального и максимального элемента этого массива. Для хранения минимального и максимального значения предусмотреть два поля класса и свойства только для чтения этих полей. Создать объект этого класса. Ввести с клавиатуры элементы массива объекта. Распечатать элементы массива объекта, минимальное и максимальное значение массива.

5. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом, а также функцию, для определения суммы и средне - арифметического значения элементов этого массива. Для хранения суммы и среднего значения предусмотреть два поля класса и свойства только для чтения этих полей. Создать объект этого класса. Ввести с клавиатуры элементы массива объекта. Распечатать элементы массива объекта, суммы и средне - арифметического значение массива.

6. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом, а также функцию, для сортировки элементов этого массива в порядке возрастания. Класс также должен содержать поля для минимального и максимального элемента массива, а также свойства только для чтения этих полей. Значения этих полей определяются в результате работы функции сортировки. Создать объект этого класса. Ввести с клавиатуры элементы массива объекта. Распечатать элементы массива объекта, минимальное и максимальное значение массива.

7. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом, а также функцию, для сортировки элементов этого массива в порядке убывания. Класс также должен содержать поля для минимального и максимального элемента массива, а также свойства только для чтения этих полей. Значения этих полей определяются в результате работы функции сортировки. Создать объект этого класса. Ввести с клавиатуры элементы массива объекта. Распечатать элементы массива объекта, минимальное и максимальное значение массива.

8. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом. Создать три объекта данного класса. Ввести с клавиатуры элементы массива для первого и второго объекта. Элементы массива третьего объекта получить путем суммирования соответствующих элементов массивов первого и второго объектов. Распечатать массив третьего объекта.

9. Объявить класс, содержащий одномерный целочисленный массив размерностью 10, индексатор для работы с этим массивом. Создать объект данного класса. Ввести с клавиатуры элементы массива объекта. Найти элемент массива наиболее близкий по своему значению средне арифметическому значению элементов массива. Распечатать значение этого элемента и его индекс.

10. Объявить класс, содержащий одномерный целочисленный массив размерностью 5, индексатор для работы с этим массивом. Создать три объекта данного класса. Ввести с клавиатуры элементы массива для первого и второго объекта. Элементы массива третьего объекта получить путем сравнения соответствующих элементов массивов первого и второго объектов и выбора наибольшего. Распечатать массив третьего объекта.

Лабораторная работа № 3

Наши рекомендации