Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Русский_Проект: Изучение Visual Basic C#.Учебный курс


C#. Учебный курс

Здравствуйте, программисты! Сегодня у нас последнее занятие по учебному курсу C#. Параллельно с выпусками я делал справочник по C#, который являлся расширенным вариантом тех материалов, которые я выкладывал в выпусках рассылки. Я уже неоднократно говорил, что основу учебного курса составлют главы из книги Г.Шилдта C#.Учебный курс. Если вы хотите дальше изучать этот язык, то купите эту книгу (Кстати, а какую еще книгу вы бы посоветовали для изучения C#?). А в справочник, помимо отрывков из этой книги, войдут и мои материалы, а также отрывки из других книг. Обладателями данного справочника могут стать любой пользователь, который приобрел у меня платные справочники. Если вы еще не покупали моих справочников, но желаете продолжить изучение учебного курса C# по моему новому справочнику (например, не хотите покупать книгу Г.Шилтда), то можете сделать символический взнос в SMS-копилку, которая находится на главной странице сайта. А последнее занятие будет посвящено классам

Классы

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

Классы — это основа любого объектно-ориентированного языка. В классе определены данные и методы для их обработки. Сама платформа .NET Framework состоит из библиотеки классов. Таким образом, класс является фундаментом, на котором построен язык C#. Наша задача с помощью C# получить доступ к этим классам для реализации своих задач. Например, при использовании класса Console мы можем воспользоваться методом WriteLine для вывода строки на экран. Класс является основой для создания объектов, который является экземпляром класса. Непосредственно инициализация переменных в объекте происходит в конструкторе.

Синтаксис определения классов на С# очень прост. Поместите перед именем вашего создаваемого класса ключевое слово class и между фигурными скобками вставьте нужные члены класса:

class MyClass
{
   private long myCat;
}

Таким образом, вы создали простейший класс с именем MyClass, который содержит пока единственный член — myCat. В классе можно также объявить не только переменные, но и методы, константы, конструкторы, дескрукторы, индексаторы, события, операторы и свойства.

Для чего нужны классы? Представьте себе, что у вас есть некоторый объект, который характеризуется рядом свойств. Например, кот. У него есть такие свойства, как имя, возраст, цвет и т. п. В этом случае удобно каждого кота описывать не рядом независимых переменных (строкового типа для имени, целого типа для возраста), а одной переменной типа Cat, внутри которой и содержатся переменные для имени, возраста и цвета. Здесь самое важное то, что в переменной типа Cat содержатся другие переменные. Конечно, типа Cat среди встроенных типов данных нет, но это не беда — мы можем ввести его. Кроме того, в классах помимо переменных разных типов содержатся функции (или, что то же самое, методы) для работы с этими переменными. Скажем, в нашем примере с классом Cat логично ввести специальную функцию для записи возраста. Функции будут, в частности, проверять правильность вводимой информации. Например, ясно, что возраст у кота не может быть отрицательным или большим 500. Так вот, наша функция и будет проверять правильность введенного пользователем возраста. Давайте рассмотрим первый пример класса. Создайте новое консольное приложение для С# и введите следующий текст:

using System;

// Создаем новый класс для котов
class Cat
{
    public int age = 0; //возраст
    public string name; //имя    
}

class AboutClass
{
    
 public static void Main()
    {
        Cat myCat = new Cat();
        myCat.age = 3;  //нашему коту 3 года
        myCat.name = "Рыжик";  //его имя
        // Выводим данные на экран
        Console.WriteLine(myCat.name);
        Console.WriteLine(myCat.age);
      }
}

Итак, мы определили новый класс Cat, внутри которого существуют две переменные, содержащии данные о возрасте и имени кота. Можно сразу же задавать начальное значение (но не обязательно). Перед переменными используем ключевое слово public. Значит, они будут видны вне класса. Если указать private (или вообще ничего не указывать), то переменная будет видна только внутри этого же класса. Далее мы создаем экземпляр нашего класса и используем его для присвоения некоторых значений для возраста и имени кота. Для проверки мы выводим эти значения на экран.

Изучение любой темы проще проводить на каком-нибудь примере. Мы разработаем класс, который инкапсулирует информацию о транспортных средствах, как легковые автомобили, фургоны и грузовики, и назовем его Vehicle. В этом классе будет храниться информация о количестве пассажиров, объем бака и другие данные (пример из книги Г.Шилдта).

Начнем с малого, создадим класс Vehicle, в котором определим несколько переменных:

class Vehicle
{
    public int passengers;    // количество пассажиров
    public int fuelcap;           // емкость бака
    public int mpg;                // расстояние, которое автомобиль может проехать, используя 1 литр 

топлива
}

Итак, мы уже объявили новый класс Vehicle, в котором содержаться полезные данные. Но, помните, что объявление класса с помощью ключевого слова class дает только описание типа, а сам объект при этом не создается. Для того, чтобы создать объект типа Vehicle, необходимо использовать ключевое слово new. Например, так:

Vehicle minivan = new Vehichle();  // создается объект типа Vehicle с именем minivan

При создании объекта в нем создаются свои собственные копии переменных passengers, fuelcap и mpg, которые мы объявляели в классе. Для доступа к этим переменным используется точка. Например, для присваивания переменной fuelcap объекта minivan значения 10 используется следующий код:

minivan.fuelcap = 10;

Теперь все готово, чтобы написать программу, которая использует класс Vehicle:

// Пример использования класса Vehicle

using System;

// Создаем класс Vehicle
class Vehicle
{
    public int passengers;    // количество пассажиров
    public int fuelcap;           // емкость бака
    public int mpg;                // расстояние, которое автомобиль может проехать, используя 1 литр 

топлива
}

// В этом классе создается объект класса Vehicle
class VehicleDemo
{
    public static void Main()
    {
        Vehicle minivan = new Vehicle();
        
        // Присваиваем значение переменным объекта minivan
        minivan.passengers = 7;
        minivan.fuelcap = 10;
        minivan.mpg = 21;

        // Вычисляем расстояние, которое способен проехать автомобиль с полным баком топлива
        int range = minivan.fuelcap * minivan.mpg;

        Console.WriteLine("Миниавтобус может перевести " + minivan.passengers + " пассажиров на 

расстояние " + range + " км");
    }
}

Итак, внутри класса VehicleDemo мы создаем экземпляр класса Vehicle с именем minivan и получаем доступ к переменным этого объекта, присваивая им значения и используя их в вычислениях. Кстати, классы Vehicle и VehicleDemo не обязательно должны находиться в одном файле. Можно поместить каждый класс в отдельный файл.

Важно понимать, что каждый объект имеет собственные копии переменных экземпляра, определенных их классом. То есть, если существует два объекта Vehicle, то каждый из них имеет собственные копии переменных passengers, fuelcap и mpg. Рассмотрим такой пример:

using System;

class Vehicle
{
    public int passengers;    // количество пассажиров
    public int fuelcap;           // емкость бака
    public int mpg;                // расстояние, которое автомобиль может проехать, используя 1 литр 

топлива
}

// Создаем два объекта класса Vehicle
class TwoVehicles
{
    public static void Main()
    {
        Vehicle minivan = new Vehicle();
        Vehicle sportcar = new Vehicle();

         // Присваиваем значение переменным объекта minivan
        minivan.passengers = 7;
        minivan.fuelcap = 10;
        minivan.mpg = 21;

        // Присваиваем значение переменным объекта sportcar
        sportcar.passengers = 2;
        sportcar.fuelcap = 14;
        sportcar.mpg = 12;

        // Вычисляем расстояние, которое способен проехать автомобиль с полным баком топлива
        int range = minivan.fuelcap * minivan.mpg;

        // Вычисляем расстояние, которое способен проехать автомобиль с полным баком топлива
        int range2 = sportcar.fuelcap * sportcar.mpg;

        Console.WriteLine("Миниавтобус может перевести " + minivan.passengers + " пассажиров на 

расстояние " + range + " км");

        Console.WriteLine("Спортивный автомобиль может перевести " + sportcar.passengers + " 

пассажиров на расстояние " + range2 + " км");
        }
}

Еще раз рассмотрим строчку кода

Vehicle minivan = new Vehicle();

Здесь выполняются два действия. Первое действие - сначала объявляется переменная типа Vehicle с именем minivan. Эта переменная не определяет объект, а только ссылается на него. Второе действие - при выполнении оператора new создается объект, а переменной присваивается ссылка на объект. Оператор new динамически выделяет память для объекта и возвращает ссылку на эту область памяти. Можно переписать предыдущий код по другому:

Vehicle minivan;  // объявляем ссылку на объект

// выделяем память для объекта Vehicle
// и возвращаем ссылку на этот объект переменной minivan
minivan = new Vehicle(); 

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

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

int iValue;
iValue = 7;

Переменная типа integer iValue хранит значение 7. Но переменная minivan не хранит объект, а хранит только ссылку на него.

При выполнении операции присваивания переменные ссылочного типа действуют иначе, чем переменные обычного типа (например, типа int). Когда мы присваиваем значение обычной переменной другой переменной, то эта переменная просто получает копию значения первой переменной. Когда же значение одной переменной ссылочного типа мы присваиваем другой переменной, то тут немного сложнее. Рассмотрим такой пример:

        Vehicle car1 = new Vehicle();
        Vehicle car2 = car1;
        int var1 = 0;
        int var2 = var1;

         // Присваиваем значение переменным
        car1.passengers = 7;
        var1 = 5;
        
        Console.WriteLine(car1.passengers);
        Console.WriteLine(car2.passengers);
        Console.WriteLine(var1);
        Console.WriteLine(var2);

Когда мы присвоили новое значение переменной car1, то переменная car2 также получила это значение, поэтому выводятся одинаковые значения в первых двух строчках WriteLine. При этом эти переменные не связаны с друг другом, но ссылаются на один объект.

На этом наши занятия заканчиваются. Объявляется перерыв. Удачного вам программирования!


©2007 А.Климов
Русский_Проект

В избранное