Понятие класса и объекта в С #
C# является полноценным объектно-ориентированным языком. Это значит, что программу на C# можно представить в виде взаимосвязанных взаимодействующих между собой объектов .
Описанием объекта является класс , а объект представляет экземпляр этого класса .
По умолчанию проект консольного приложения по умолчанию содержит один класс Program , с которого и начинается выполнение программы.
Класс представляет новый тип, который определяется пользователем. Класс определяется с помощью ключевого слова сlass :
[ атрибуты ] [ спецификаторы ] class имя_класса [ : предки ]
{тело_класса}
Класс можно определять внутри пространства имен, вне пространства имен, внутри другого класса. Классы помещаются в отдельные файлы.
Для того, чтобы воспользоваться классом, необходимо создать его экземпляр . Экземпляр класса - это реальный объект, для которого выделена память и установлены значения всех свойств. Для класса "человек" экземпляром будет конкретный индивид со своим цветом волос, ростом, весом и номером паспорта.
Поместим новый класс в файле, где располагается класс Program. То есть файл Program.cs будет выглядеть следующим образом:
using System;
namespace HelloApp
{
class Person
{
}
class Program
{
static void Main(string[] args)
{
}
}
}
Спецификаторы определяют свойства класса, а также доступность класса для других элементов программы.
Спецификаторы со второго по шестой называются спецификаторами доступа . Они определяют, откуда можно непосредственно обращаться к данному классу. Спецификаторы доступа могут комбинироваться с остальными спецификаторами.
Класс можно описывать непосредственно внутри пространства имен или внутри другого класса. В последнем случае класс называется вложенным. В зависимости от места описания класса некоторые из этих спецификаторов могут быть запрещены. Будем рассматривать классы, которые описываются непосредственно в пространстве имен. Для таких классов допускаются только два спецификатора: public и internal . По умолчанию, то есть если ни один спецификатор доступа не указан, подразумевается спецификатор internal .
Объекты создаются явным или неявным образом, то есть либо программистом, либо системой. Программист создает экземпляр класса с помощью операции new , например:
Demo a = new Demo (); // Создается экземпляр класса Demo
Для каждого объекта при его создании в памяти выделяется отдельная область, в которой хранятся его данные. В классе могут присутствовать статические элементы , которые существуют в единственном экземпляре для всех объектов класса. Статические данные часто называют данными класса , а остальные - данными экземпляра . Для работы с данными класса используются статические методы класса , для работы с данными экземпляра - методы экземпляра , или просто методы .
В общем случае класс может содержать следующие функциональные элементы:
- Данные : переменные или константы.
- Методы , реализующие не только вычисления, но и другие действия, выполняемые классом или его экземпляром.
- Конструкторы (реализуют действия по инициализации экземпляров или класса в целом).
- Свойства (определяют характеристики класса в соответствии со способами их задания и получения).
- Деструкторы (определяют действия, которые необходимо выполнить до того, как объект будет уничтожен).
- Индексаторы (обеспечивают возможность доступа к элементам класса по их порядковому номеру).
- Операции (задают действия с объектами с помощью знаков операций).
- События (определяют уведомления, которые может генерировать класс).
- Типы (типы данных, внутренние по отношению к классу).
Вся функциональность класса представлена его членами - полями (Полями называются переменные класса), свойствами, методами, событиями . Например, определим в классе Person поля и метод:
using System;
namespace HelloApp
{
class Person
{
public string name; // имя
public int age; // возраст
public void GetInfo()
{
Console.WriteLine($" Имя : {name} Возраст : {age}");
}
}
class Program
{
static void Main(string[] args)
{
Person tom;
Console.ReadKey();
}
}
}
В данном случае класс Person представляет человека. Поле name хранит имя, а поле age - возраст человека. А метод GetInfo выводит все данные на консоль. Чтобы все данные были доступны вне класса Person переменные и метод определены с модификатором public.
Так как класс представляет собой новый тип, то в программе мы можем определять переменные, которые представляют данный тип. Так, здесь в методе Main определена переменная tom, которая представляет класс Person. Но пока эта переменная не указывает ни на какой объект и по умолчанию она имеет значение null . Поэтому вначале необходимо создать объект класса Person.
Person tom = new Person();
Данные: поля и константы
Данные, содержащиеся в классе, могут быть переменными или константами . Задаются они в соответствии с правилами, рассмотренными для имен переменных. При описании данных также можно указывать атрибуты и спецификаторы, задающие различные характеристики элементов.
Синтаксис описания элемента данных:
[атрибуты] [спецификаторы] [const] тип имя [ = начальное значение ]
По умолчанию элементы класса считаются закрытыми private . Для полей класса этот вид доступа является предпочтительным, поскольку поля определяют внутреннее строение класса, которое должно быть скрыто от пользователя. Все методы класса имеют непосредственный доступ к его закрытым полям.
Поля, описанные со спецификатором static , а также константы существуют в единственном экземпляре для всех объектов класса, поэтому к ним обращаются через имя класса . Обращение к полю класса выполняется с помощью операции доступа (точка). Справа от точки задается имя поля, слева - имя экземпляра для обычных полей или имя класса для статических. Рассмотрим пример создания класса и два способа обращения к его полям.
class Circle
{
public int x=0;
public int y=0;
public int radius=3;
public const double pi = 3.14;
public static string name = " Окружность ";
double p;
double s;
}
class Program
{
static void Main()
{
Circle cr = new Circle(); // создание экземпляра класса
Console.WriteLine("pi=" + Circle.pi);// обращение к константе
Console.Write(Circle.name);// обращение к статическому полю
//обращение к обычным полям
Console.WriteLine(" с центром в точке ({0},{1}) и радиусом {2}", cr.x, cr.y, cr.radius);
// Console.WriteLine(cr.p); - вызовет ошибку, т.к. поле p имеет тип private
Console.Write("Введите коэффициент= ");
int kof = int.Parse(Console.ReadLine());
cr.x -= kof; cr.y += kof; cr.radius *= kof;
Console.WriteLine(" Новая окружность с центром в точке ({0},{1}) и радиусом {2}",
cr.x, cr.y, cr.radius);
//cr.s = 2 * Circle.pi * cr.radius; - вызовет ошибку, т.к. поле s имеет тип private
}
}
Методы
Методы находятся в памяти в единственном экземпляре и используются всеми объектами одного класса совместно, поэтому необходимо обеспечить работу методов нестатических экземпляров с полями именно того объекта, для которого они были вызваны. Для этого в любой нестатический метод автоматически передается скрытый параметр this , в котором хранится ссылка на вызвавший функцию экземпляр.
Ключевое слово this представляет ссылку на текущий экземпляр класса.
В явном виде параметр this применяется для того, чтобы возвратить из метода ссылку на вызвавший объект, а также для идентификации поля в случае, если его имя совпадает с именем параметра метода.
class Circle
{
public int x=0;
public int y=0;
public int radius=3;
public const double pi = 3.14;
public static string name = " Окружность ";
public Circle T() //метод возвращает ссылку на экземпляр класса
{
return this;
}
public void Set(int x, int y, int r)
{
this.x = x;
this.y = y;
radius=r;
}
}
class Program
{
static void Main()
{
Circle cr = new Circle(); // создание экземпляра класса
Console.WriteLine("pi=" + Circle.pi);// обращение к константе
Console.Write(Circle.name);// обращение к статическому полю
//обращение к обычным полям
Console.WriteLine(" с центром в точке ({0},{1}) и радиусом {2}", cr.x, cr.y, cr.radius);
cr.Set(1, 1, 10);
Console.WriteLine("Новая окружность с центром в точке ({0},{1}) и радиусом {2}",
cr.x, cr.y, cr.radius);
Circle b=cr.T();//получаем ссылку на объект cr, аналог b=c
Console.WriteLine("Новая ссылка на окружность с центром в точке ({0},{1})
и радиусом {2}", b.x, b.y, b.radius);
}
}
Благодаря такой системе модификаторов доступа можно скрывать некоторые моменты реализации класса от других частей программы. Такое сокрытие называется инкапсуляцией .
Инициализаторы объектов
Для инициализации объектов классов можно применять инициализаторы. Инициализаторы представляют передачу в фигурных скобках значений доступным полям и свойствам объекта:
Person tom = new Person { name = "Tom", age=31};
tom.GetInfo(); // Имя : Tom Возраст : 31
С помощью инициализатора объектов можно присваивать значения всем доступным полям и свойствам объекта в момент создания без явного вызова конструктора.