Класс в программировании: что это такое и как использовать

Класс в программировании: что это такое и как использовать Полезное

Класс — это шаблон (тип данных), по которому создаются объекты: он описывает, какие данные хранит объект и какие действия с ними можно выполнять. Класс сам по себе ничего не делает и не занимает памяти под данные — это чертеж. По этому чертежу программа создает конкретные объекты (их называют экземплярами), и уже они хранят реальные значения. Ниже разберем, чем класс отличается от объекта, из чего он состоит (поля, методы, конструктор) и как работают наследование и инкапсуляция. Примеры — на Python, с фактическим выводом; ключевые идеи одинаковы в Java, C#, C++ и других языках.

Класс и объект: в чем разница

Проще всего понять на аналогии. Класс — это чертеж дома, а объект — конкретный построенный по нему дом. Чертеж один, домов по нему можно построить сколько угодно, и у каждого будут свои значения: цвет, площадь, адрес.

В коде это выглядит так. Объявляем класс Dog, а затем создаем два независимых объекта:

class Dog:
    def __init__(self, name, age):
        self.name = name   # поле: кличка
        self.age = age     # поле: возраст

dog1 = Dog("Рекс", 3)
dog2 = Dog("Белка", 5)

print(dog1.name, dog1.age)
print(dog2.name, dog2.age)
print(type(dog1))

Вывод:

Рекс 3
Белка 5
<class '__main__.Dog'>

dog1 и dog2 — разные объекты одного класса. Изменение dog1.age никак не затронет dog2. Класс задает структуру («у собаки есть кличка и возраст»), а объект хранит конкретные данные.

Из чего состоит класс

Класс собирается из нескольких частей. Разберем их по очереди.

Часть Что это Пример
Поле (атрибут) Данные, которые хранит объект self.name, self.age
Метод Функция внутри класса, действие объекта bark(), birthday()
Конструктор Специальный метод, задающий начальные значения __init__
self Ссылка на сам объект внутри методов self.name

Поля и методы

Поля хранят состояние объекта, методы — его поведение. Метод отличается от обычной функции тем, что первым параметром получает сам объект (в Python это self) и работает с его полями.

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        return f"{self.name} говорит: гав!"

    def birthday(self):
        self.age += 1

dog = Dog("Рекс", 3)
print(dog.bark())
dog.birthday()
print(dog.age)

Вывод:

Рекс говорит: гав!
4

Метод birthday() меняет поле age конкретного объекта. Это и есть суть ООП: данные и действия над ними лежат вместе, внутри объекта.

Конструктор

Конструктор вызывается автоматически при создании объекта и задает его начальное состояние. В Python это метод __init__, в Java и C# — метод с именем класса, в C++ — тоже.

Именно поэтому нельзя «просто обратиться к объекту» без создания: сначала конструктор должен собрать объект. Если обязательный аргумент не передать, программа сразу сообщит об ошибке:

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

dog = Dog("Рекс")   # забыли передать age

Фактический вывод:

TypeError: Dog.__init__() missing 1 required positional argument: 'age'

Исправление — передать все аргументы, которые ждет конструктор:

dog = Dog("Рекс", 3)   # работает

Наследование

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

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "Животное издает звук"

class Cat(Animal):          # Cat наследует от Animal
    def speak(self):        # переопределяем метод
        return f"{self.name} говорит: мяу!"

cat = Cat("Мурка")
print(cat.name)      # поле досталось от Animal
print(cat.speak())   # метод переопределен в Cat

Вывод:

Мурка
Мурка говорит: мяу!

Класс Cat не описывает поле name заново — оно унаследовано. А метод speak() переопределен под кота. Наследование удобно, когда классы связаны отношением «частный случай общего» (кот — это животное). Если такой связи нет, лучше не наследовать, а хранить один объект внутри другого (композиция).

Инкапсуляция и модификаторы доступа

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

В Java и C# для этого есть ключевые слова private (доступ только внутри класса) и public (доступ отовсюду). В Python строгого запрета нет: подчеркивание перед именем — это соглашение, сигнал «не трогай снаружи», а двойное подчеркивание запускает искажение имени и усложняет доступ.

class Account:
    def __init__(self):
        self.__balance = 0        # спрятанное поле

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def get_balance(self):
        return self.__balance

acc = Account()
acc.deposit(100)
print(acc.get_balance())

Вывод:

100

Пополнить счет можно только через deposit, который проверяет сумму. Прямая попытка acc.__balance приведет к ошибке:

AttributeError: 'Account' object has no attribute '__balance'

Так метод-«привратник» не дает записать в баланс отрицательное или мусорное значение.

Частые ошибки новичков

Тройка типичных проблем при работе с классами.

  1. Забыть self в методе. Тогда обращение к полю не находит объект:
class Point:
    def __init__(self, x):
        self.x = x
    def show():          # пропущен self
        return x

Point(5).show()

Вывод:

TypeError: Point.show() takes 0 positional arguments but 1 was given

Исправление — добавить self: def show(self): return self.x.

  1. Путать класс и объект. Вызов Dog.bark() без создания объекта не сработает — метод ждет конкретный объект в self. Сначала нужно dog = Dog(...), потом dog.bark().

  2. Обращаться к объекту до конструктора. Пропущенный обязательный аргумент __init__ дает TypeError (пример выше). Передавайте все аргументы, которые объявлены в конструкторе.

Выводы

  • Класс — это шаблон (тип), а объект — конкретный экземпляр, созданный по этому шаблону; класс описывает структуру, объект хранит данные.
  • Класс состоит из полей (данные) и методов (поведение); конструктор задает начальное состояние объекта при его создании.
  • В Python конструктор — это __init__, а self внутри методов — ссылка на текущий объект.
  • Наследование переиспользует код: класс-потомок получает поля и методы родителя и может их переопределить; применять его стоит для связи «частный случай общего».
  • Инкапсуляция скрывает данные за методами, чтобы объект защищал свое состояние; в Java и C# это private/public, в Python — соглашение об именах с подчеркиванием.
  • Основные идеи классов одинаковы в Python, Java, C#, C++ — меняется только синтаксис.

Где применяется / связь с практикой

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

Освойте тему на практике

Разобраться с классами на практике, а не только в теории, помогает системный курс с проверкой заданий. Основы ООП на Python подробно разбирают на курсе Python Basic. Если сначала хочется просто посмотреть, как проходит обучение, загляните на бесплатные вебинары — там можно вживую задать вопросы преподавателю.

Смежные темы: Databases: классификация, Серверы: классификация и предназначение.

FAQ

Нужно ли всегда писать конструктор? Нет. Если объекту не нужны начальные данные, конструктор можно не писать — язык подставит пустой по умолчанию. Он нужен, когда при создании объекта надо сразу задать значения полей.

Класс и структура (struct) — это одно и то же? Близко, но не всегда. В C++ разница минимальна (у struct поля по умолчанию public, у class — private). В C# struct — это тип-значение, он копируется целиком, а класс передается по ссылке; выбор влияет на поведение при копировании.

Может ли класс наследовать сразу от нескольких классов? Зависит от языка. В Python и C++ множественное наследование разрешено, в Java и C# — нет (там наследуются от одного класса, но реализуют несколько интерфейсов).

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)