Уроки OpenGL + C#.

Разработка класса и реализация консольной программы на основе разрабатываемого класса.

Рассмотрим работу с классами в C# на примере.

Сейчас мы рассмотрим пример создания небольшого класса.

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

Создадим новый класс, Назовем его Man (человек).

Наш класс будет схематично описывать человека следующим образом:

Описание класса. Имя, возраст, здоровье и состояние жив / мерт будут описывать каждый конкретный экземпляр нашего класса - на основе этих параметров так же будет основываться работа функций Talk, Go, Kill и IsAlive.

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





 

Создадим новое консольное приложение, и назовем его ClassTesting
После сгенерированного програмой класса Program, мы создадим свой класс, назвав его Man, и снабдив его необходимыми свойствами и методами:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassTesting
{

class Program
{
static void Main(string[] args)
{

 

}

}

 

 

public class Man
{
// конструктор класса (данная функция вызывается
// при создании нового экземпляра класса

public Man(string _name)
{
Name = _name;
isLife = true;
}

 

// закрытые члены, которые нельзя именить
// извне класса

// строка, содержащая имя
private string Name;

// беззнаковое целое число, содержащая возраст
private uint Age;

// беззнаковое целое число, отражающее уровень здоровья
private uint Health;

// булево, означающее жив ли данный человек
private bool isLife;

// заготоква функции "говорить"
public void Talk()
{

}

// заготовка функции "идти"
public void Go()
{

}

// функция, возвращающая показатель - жив ли данный человек.
public bool IsAlive()
{
// возращаем значение, к которому мы не можем
// обратиться на прямую из вне класса,
// так как оно имеет статус private

return isLife;
}

}

 

}

Вот такая вот заготовка нашей программы. Как видите мы добавили еще одну функцию, о которой забыли в схеме нашего класса IsAlive.
Данная функция будет возвращать значение переменной isLife, к которой мы не можем получить доступ извне класса, так как она является закрытой (private).

Теперь более тщательно займемся реализавцией наших классов.
Во первых улучшим конструктор класса: в нем будут генерироваться состояния здоровья и возраст нашего человека, случайным образом. Для этого мы будем использовать класс генерации случайных числел.
Random в C#. Генерация случайного числа в C#.

Хорошее знание языков программирования никогда не обходится без знания того, как выполняется генерация случайных чисел. Сейчас мы рассмотрим то, как выполняется генерация случайного числа в С#.
Для выполнения данной задачи сначало создадим новый экземпляр класса Random

Random rnd = new Random();

Теперь для того, чтобы получить случайное число достаточно использовать созданный экземпляр класса, вызвая метод Next(); , например

Age = rnd.Next();

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

// конструктор класса (данная функция вызывается
// при создании нового экземпляра класса


public Man(string _name)
{
// получаем имя человека из входного праметра
// конструктора класса

Name = _name;
// экземпляр жив
isLife = true;

 

// генерируем возраст от 15 до 50
Age = (uint)rnd.Next(15,50);
// и здоровье, от 10 до 100%
Health = (uint)rnd.Next(10, 100);

}

(uint) перед экземпляром класса rnd означает, что значение случайного числа, которое вернет функия Next будет приведено к типу uint (unsigned – т.е. беззнаковое int). Просто функция rnd возвращает значение с типом int, и данное значение не может быть неявно преобразовано, поэтому необходимо сообщить компилятору о пребразовании.
Полсе конструктора класса, добавим объявление нашего экземплюяра класса Random

// экземпляр класса Random
// для генерации случайных чисел


private Random rnd = new Random();


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

 

Начало кода фукции будит таким

 


// заготоква функции "говорить"
public void Talk()
{
// генерируем случайное число от 1 до 3
int random_talk = rnd.Next(1, 3);

// объявляем переменную, в которой мы будем хранить
// строку

 

string tmp_str = "";

Как видите здесь мы объявляем переменную random_talk, и сразу при объявлении она получает значение – результат выполнения функции rnd.Next, в диапазоне от 1 до 3.
В зависимости от этого значения, при вызове функции Talk случайным образом будет происходить выбор, что же сейчас скажет наш объект.
Далее мы объявляем переменную, в которой будет храниться значение строки, которую мы сгенерируем.
Генерация строки будет выполняться с помощью оператора выбора switch:


 


// в зависимости от случ значения random_talk
switch
(random_talk)
{

case 1: // если 1 - называем свое имя
{
// генериуем текст сообщения
tmp_str = "Привет, меня зовут " + Name + ", рад познакомиться";

 


// завершаем оператор выбора
break;
}

case 2: // возраст
{
// генериуем текст сообщения
tmp_str = "Мне " + Age + ". А тебе?";
// завершаем оператор выбора
break;
}

case 3: // говорим о своем здоровье
{

// в зависимости от параметра здоровья

if (Health > 50)
tmp_str = "Да я зводоров как бык!";
else
tmp_str = "Со здоровьем у меня хреново, дожить бы до " + (Age + 10).ToString();

 



// завершаем оператор выбора
break;
}
}

 

Как видно из кода, в зависимости от значения переменной random_talk выполняется ветвление кода, и выбирается одна из веток для значения random_talk = 1 (case 1), random_talk = 2 (case 2), или random_talk = 3 (case 3).
Ну, и собственно, завершение функции

 

// выводим в консоль сгенерированное сообщение
System.Console.WriteLine(tmp_str);

}

Теперь рассмотрим код функции Go.

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


// заготовка функции "идти"
public void Go()
{
// если объект жив
if (isLife == true)
{
// если показатель более 40
// считаем объект здоровым

if (Health > 40)
{
// генерируем строку текста
string outString = Name + " мирно прогуливается по городу";
// выводим в консоль
System.Console.WriteLine(outString);
}
else
{
// генерируем строку текста
string outString = Name + " болен и не может гулять по городу";
// выводим в консоль
System.Console.WriteLine(outString);
}
}
else
{
// генерируем строку текста
string outString = Name + " не может идти, он умер";
System.Console.WriteLine(outString);
}

 

}


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

 

public void Kill()
{
// устанавливаем значение isLife (жив)
// в false...

isLife = false;
}

Вот в принципе и все. Если вы набрали весь код верно, то при компиляции (клавиша F5) не должно возникнуть никаких проблем.
Теперь вернемся к коду главного класса (Program)

Нам необходимо сделать так, чтобы консоль ожидала команды пользователя: в зависимости от этих команд будут выполняться различные действия – создания новых экземпляров класса Man (так сказать создание новых людей :-) ), и выполнение функций, которые реализованы в классе Man

Для этого мы создадим бесконечный цикл: в нем программа будет запрашивать пользователя ввести строку. Затем строка будет сверяться с заданным набором команд при помощи оператора выбора (switch).
В зависимости от той или иной команды, будут выполняться действия над нашим человеком. Команда exit будет завершать программу. Снчала посмотрим как будет происходить ввод строки и выбор команды.

Первым делом объявим переменную user_command в которой мы будем хранить команду, введенную пользователем, далее мы объявим переменную Infinity . До тех пор пока значение Infinity будит равно true, цикл будет выполняться. Изменеие этой переменной произойдет, только если пользователь введет команду exit

 


static void Main(string[] args)
{

// переменная, которая будет хранить команду пользователя
string user_command = "";

 

// бесконечный цикл
bool Infinity = true;

while (Infinity) // пока Infinity равно true
{
// приглашение ввести команду
System.Console.WriteLine("Пожалуйста, введите команду");

// получение строки (команды) от пользователя
user_command = System.Console.ReadLine();

Далее, из кода видно, что мы начинаем наш цикл while
При старте выполнения кода из тела цилка, сначала в консоль выводиться строка, с приглашением ввести команду. Далее мы ожидаем ввода строки пользователем. Введенная строка , после нажатия клавиши enter будет записана в переменную user_command.
Теперь , с помощью операции ветвления, мы создадим обработку стандартных команд : exit и help.
Ветвление default будет выполняться в том случае, если введеная строка не будет соответствовать ни одной введенной команде.


// обработка команды с помощью оператора ветвления
switch (user_command)
{

// если user_command содержит строку exit

case "exit":
{
Infinity = false;
// теперь цикл завершиться, и программа завершит свое выполнение
break;
}

 

// если user_command содержит строку help
case "help":
{

System.Console.WriteLine("Список команд:");
System.Console.WriteLine("---");

System.Console.WriteLine("create_man : команда создает человека, (экземпляр класса Man)");
System.Console.WriteLine("kill_man : команда убивает человека");
System.Console.WriteLine("talk : команда застравляет человека говорить (если создан экземпляр класса)");
System.Console.WriteLine("go : команда застравляет человека идти (если создан экземпляр класса)");

 

System.Console.WriteLine("---");
System.Console.WriteLine("---");

break;

}

// если команду определить не удалось
default:
{

System.Console.WriteLine("Ваша команда не определена, пожалуйста повторите снова");
System.Console.WriteLine("Для вывода списка команд введите команду help");
System.Console.WriteLine("Для завершения программы введите команду exit");
break;
}

 

}

Не забульте закрыть все фигурные скобки ( } ) после операции ветвления.
Таким образом, теперь, если мы откомпелируем проект (клавиша F5), то мы увидем окно консоли, с приглашение ввести команду.

Пример выполнения команд из консоли.
Рисунок 1.

Теперь нам осталось лишь реализовать обработку команд create_man, kill_man, talk и go.
После строки объявления переменной и перед началом цилка while добавьте объявления экземпляра класса Man.

// пустой (раный null) экземпляр класса Man

Man SomeMan = null;

Теперь рассмотрим код обработки команды crete_man в теле оператора ветвления (switch)

 

case "create_man":
{
// проверяем, создан ли уже какой либо человек
if (SomeMan != null)
{
// человек уже существует.
// убиваем его
// (это не обязательная операция синтаксиса языка
// а всего лишь каприз автора кода :), вы можите пропустить эту строку)

SomeMan.Kill();

 

}

// просим ввести имя человека
System.Console.WriteLine("Пожалуйста, введите имя создаваемого человека ");

// получаем строку введенную пользователем
user_command = System.Console.ReadLine();

// создаем новый объект в памяти, в качесвте параметра
// передаем имя человека

SomeMan = new Man(user_command);

// сообщаем о создании
System.Console.WriteLine("Человек успешно создан ");

break
;

}

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

 


case "kill_man":
{
// проверяем, что объект существует в памяти
if (SomeMan != null)
{
// вызываем фукнцию сметри
SomeMan.Kill();
}

 


break;
}


Это код фунции смерти.

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

Мы делаем это , проверяя, не равен ли наш объект (к примеру SomeMan) null. Если не выполнить такую провеку, а потом в ходе работы программы окажется что , к примеру, SomeMan = null и мы попытаемся вызвать лубой из его методов (кроме конструктора класса – он как раз и создает объект в памяти), то в программе произайдет ошибка и обработка исключения.
Для того чтобы, к примеру, выполнить функцию kill( ); , компилятор сначала получает адрес памяти, где сейчас храниться экземпляр нашего класса. SomeMan как раз должен хранить этот адрес, а он будет равен null. Следовательно компилятор посути получит команду “по адресу null определить адресс фунции Kill и выполнить ее”. У него это конечно не получиться.

Собственно, нам остались команды talk и go
Они будут реализованы так же как и команда kill: нам достаточно проверить что объект существует в памяти. Если он существует – выполнить метод. Если нет – сообщить об этом.

 

case "talk":
{
// проверяем, что объект существует в памяти
if (SomeMan != null)
{
// вызываем фукнцию разговора
SomeMan.Talk();
}
else // иначе
{
System.Console.WriteLine("Человек не создан. Команда не может быть выполнена");
}

 

break;

}

 

case "go":
{

// проверяем, что объект существует в памяти
if (SomeMan != null)
{
// вызываем фукнцию передвижения
SomeMan.Go();
}
else
{
System.Console.WriteLine("Человек не создан. Команда не может быть выполнена");
}

 

break;

}

 

Пример работы откомпелированной программы

Пример работы написанной программы.
Рисунок 2.

 

 

Исходный код данного урока (для VS 2008).


Обсуждение данного урока: Разработка класса в C# и реализация консольной программы на основе этого класса.
Далее: 2.1 Основы Windows.Forms