Классы и функции
Что и когда лучше использовать, чтобы писать хороший код.
Мы продолжаем рассказ об объектно-ориентированном программировании: зачем оно нужно и в чём его сила. Это скорее теория, чем необходимая ежедневная практика, но такие вещи приводят в порядок картину мира.
👉 Если вы пишете простые программы для себя, все эти вещи вам могут не пригодиться. Но если хотите стать профессионалом — добро пожаловать.
🤔 Это обновлённая версия статьи. В старой были огрехи, которые мы постарались исправить, чтобы статья стала яснее и корректнее.
Вспоминаем основные понятия
Что есть класс
Вы можете изготовить объект вручную из любых функций и данных, которые вам нужны. Но если вам для работы программы нужны десятки похожих друг на друга объектов, имеет смысл как-то их стандартизировать.
Если по-простому, то класс — это «чертёж», по которому вы можете изготовить объекты. Вы прописываете один класс, определяете его поведение и свойства, а потом даёте команду создать на основе этого класса нужное число объектов.
Пример: объекты, классы и функции в игре
Если бы вы писали всё на функциях, у вас были бы такие функции:
Это довольно большой зоопарк из функций, делать так не надо. Гораздо лучше создать объекты, а внутрь к ним положить нужные функции:
Представим, что каждый персонаж игры — это объект. Внутри объекта что-то лежит
Чтобы не прописывать все эти функции и объекты вручную, мы создадим класс «Персонаж»:
имя: тут будет имя;
тип: герой или враг;
здоровье: 100;
функция «Выстрелить» <тут описываем, как стрелять>;
функция «Подлечиться» <тут описываем, как лечиться>;
Теперь мы можем создавать сколько угодно персонажей, например, так:
Новый Персонаж (имя:Герой);
Новый Персонаж (имя:Враг1, здоровье: 10);
Новый Персонаж (имя:Враг2, здоровье: 20);
Допустим, мы решили добавить в нашу игру систему инвентаря. Чтобы не ходить по всем нашим врагам и героям и не копипастить в них код, мы пропишем эту систему внутри класса:
имя: тут будет имя;
тип: герой или враг;
здоровье: 100;
функция «Выстрелить» <тут описываем, как стрелять>;
функция «Подлечиться» <тут описываем, как лечиться>;
инвентарь: [сапоги-скороходы, меч-кладенец];
функция «Сбросить_инвентарь» <как сбрасывать>;
функция «Подобрать_предмет» <как подбирать>;
Теперь у всех персонажей появился инвентарь. по умолчанию у всех там лежат сапоги и меч, но при создании персонажа это можно переопределить. Также у всех персонажей появилась возможность сбросить весь инвентарь или подобрать предмет с земли.
Заметьте, что всё это мы добавили в одном месте, а появилось всё сразу у всех. В этом сила класса.
‘ src=’https://thecode.media/wp-content/uploads/2020/09/4.png’ alt=’Объектно ориентированное программирование’>
Где применять классы и ООП, а где — функции
Если вы делаете простую программу, которую можно сделать тремя функциями — делайте. Или даже если программа станет сложнее, в ней будет много функций, но все они логично связаны и понятно, почему сделано именно так, — тоже хорошо. Нет ничего плохого в том, что вы не используете объектно-ориентированное программирование там, где можно обойтись без него.
А вот если у вас проект со множеством абстракций, взаимосвязей внутри и вы заранее не можете предсказать, когда что с чем будет взаимодействовать, то лучше использовать классы и все преимущества ООП. Возможно, код станет сложнее, но это не всегда так. С другой стороны, вы сможете реализовать такую логику, которую на функциях было бы сделать непросто.
Что такое классы в объектно-ориентированном программировании
Глубокое погружение в самую сложную и неинтуитивную область программирования.
В этом цикле статей мы говорим об объектно-ориентированном программировании — передовом и очень распространённом подходе к разработке. Это стоит знать всем, кто серьёзно относится к программированию и хочет зарабатывать в этой области.
Если не читали предыдущую статью, вот краткое содержание:
Одно из преимуществ ООП — не нужно много раз писать один и тот же код. Можно однажды придумать какую-то красивую штуку и потом заново её использовать буквально одной строкой. Для этого и нужны классы.
Что за классы
Вот одно из формальных определений класса: «Класс — это элемент ПО, описывающий абстрактный тип данных и его частичную или полную реализацию»
Если более по-русски, то класс — это шаблон кода, по которому создаётся какой-то объект. Это как рецепт приготовления блюда или инструкция по сборке мебели: сам по себе класс ничего не делает, но с его помощью можно создать новый объект и уже его использовать в работе.
Если пока непонятно, погружайтесь в пример:
Призовём на помощь силу примеров и поговорим про сотовые телефоны.
Допустим, вы делаете мобильники и хотите выпустить на рынок новую модель. Чтобы люди могли сразу пользоваться вашим устройством и быстро к нему привыкли, у телефона должен быть экран, кнопки включения и громкости, камеры спереди и сзади, разъём для зарядки и слот для сим-карты.
Но одного железа недостаточно — нужно соединить его между собой так, чтобы всё работало без сбоёв. Кроме этого, нужно предусмотреть, что происходит при нажатии на кнопки, что выводится на экран и как пользователь будет управлять этим телефоном.
Следующий этап — описать каждую деталь, из которой состоит телефон, каждую микросхему и плату, и объяснить, как детали работают друг с другом. Последний шаг — написать руководство пользователя, где будет полностью рассказано, что можно делать с телефоном, как запустить звонилку или отправить смс.
Мы только что сделали новый класс для телефона — полный набор нужных знаний, описаний, свойств и инструкций, который описывает нашу модель. Все эти инструкции и описания — это ещё не телефон, но из них этот телефон можно сделать.
В программировании у класса есть наборы данных — в нашем случае это комплектующие для телефона. Ещё есть функции для работы с классами, которые называются методами — это то, как пользователь будет работать с нашим телефоном, что он будет на нём делать и каким образом.
Классы на практике
Все примеры дальше мы будем делать на Python, потому что это стильно, модно и молодёжно. А сам Python — очень объектно-ориентированный язык, почти всё в нём — это объекты. Вот и опробуем.
Допустим, мы пишем интернет-магазин с системой скидок. Нам нужно работать с пользователями — постоянными покупателями. Пользователь у нас будет объектом: у него будет имя, возраст и адрес доставки по умолчанию. Мы заведём класс, который поможет нам инициировать нового покупателя.
Здесь сказано: «Вот класс для покупателя. У него есть три свойства: имя, возраст и адрес». Теперь мы можем заводить новых покупателей одной строкой:
# Создаём первого покупателя
# Создаём второго покупателя
Что дальше
В следующем материале мы смоделируем реальную ситуацию: добавим программу лояльности, бонусные баллы и расскажем, как Python с этим справится. Чтобы было интереснее, будем писать код на двух языках сразу — Python и JavaScript.
Объектно-ориентированное программирование. Часть 1. Что такое классы и объекты
Почти всё современное программирование построено на принципах ООП, поэтому их должен понимать каждый разработчик. Узнайте основы из этой статьи.
Введение
Это первая статья из серии, посвященной объектно-ориентированному программированию. Она предназначена для тех, кто хочет понять саму суть этой парадигмы разработки, а не просто научиться использовать классы и объекты.
Цикл состоит из статей, посвященных различным аспектам ООП:
Все примеры в этой серии мы рассмотрим на языке C#. Для наглядности они будут связаны с разработкой игр, потому что в них активно используются объекты.
Перед чтением этой серии статей вам нужно ознакомиться с такими понятиями:
Работа будет происходить в Visual Studio 2019, но вполне подойдет и VS 2017.
В конце каждой статьи будут задания, которые помогут закрепить тему. Выполнив задание, загружайте его на GitHub и пишите в комментариях ссылку на репозиторий — я постараюсь проверить каждое решение и дать обратную связь (но я всего лишь человек).
Выполнять задания не обязательно, но без практики просто невозможно осилить такую сложную тему, как ООП. Если же вам все равно лень выполнять задания, можете просто посмотреть мой вариант решения, который я также буду публиковать в комментариях.
Пишет о разработке сайтов, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.
Что такое ООП
Объектно-ориентированное программирование (сокращенно ООП) — это парадигма разработки программных систем, в которой приложения состоят из объектов.
Объекты — это сущности, у которых есть свойства и поведение. Обычно объекты являются экземплярами какого-нибудь класса. Например, в игре может быть класс Character (персонаж), а его экземплярами будут hero или npc.
Свойства — это данные, которые связаны с конкретным объектом:
Поведение объекта определяется с помощью методов — специальных блоков кода, которые можно вызывать из разных частей программы. Например, у того же объекта Character могут быть следующие методы:
Используя эти свойства и методы, можно значительно ускорить разработку, сделать код более читаемым. К тому же самому программисту проще составлять код, если он думает с помощью объектов.
То есть он не пишет какую-то функцию, которая будет делать что-то для программы в целом. Вместо этого он мысленно разделяет приложение на отдельные компоненты и продумывает их свойства и поведение.
Такую парадигму используют многие популярные языки:
Плюсы и минусы объектно-ориентированного программирования
Плюсы | Минусы |
---|---|
Легко читается. Не нужно выискивать в коде функции и выяснять, за что они отвечают. | Потребляет больше памяти. Объекты потребляют больше оперативной памяти, чем примитивные типы данных. |
Быстро пишется. Можно быстро создать сущности, с которыми должна работать программа. | Снижает производительность. Многие вещи технически реализованы иначе, поэтому они используют больше ресурсов. |
Проще реализовать большой функционал. Так как на написание кода уходит меньше времени, можно гораздо быстрее создать приложение с множеством возможностей. | Сложно начать. Парадигма ООП сложнее функционального программирования, поэтому на старт уходит больше времени. |
Меньше повторений. Не нужно писать однотипные функции для разных сущностей |
Как использовать классы и объекты
Изучая C#, разработчик в первый же день сталкивается с классами и объектами. Например, вот как выглядит первая программа любого новичка:
Здесь создается класс Program, у которого есть метод Main () — с него начинается выполнение программы, поэтому его называют точкой входа.
Для вывода текста используется следующий оператор:
Тут программа обращается к объекту Console и вызывает метод WriteLine (), который выводит переданное значение в консоль.
Также у объекта Console есть разные свойства:
Если бы не было объекта, было бы сложно определить, цвет какого фона и какого шрифта будет указываться, потому что их в программе может быть несколько.
Программирование на C, C# и Java
Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы
ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode
Что такое класс в ООП
Класс – это ключевое понятие в объектно-ориентированном программировании. Не до конца понимая, что такое класс, невозможно успешно программировать в рамках парадигмы ООП. Данная статья посвящена понятию класса и его базовым элементам, таким как поля, методы и конструкторы.
Когда Вы переходите от процедурных языков (Си, Pascal, Basic) к объектно-ориентированным (C#, Java, C++), первое, что вам нужно сделать – это сломать своё мышление относительно того, что программирование – это написание функций и их последовательный вызов в некоторой главной (main). В рамках ООП вам придётся мыслить более абстрактно и работать с классами, которые являются воплощением объектов реального мира. Казалось бы, почему мыслить в рамках реальных объектов – это значит мыслить более абстрактно?
В программировании, которое изначально было процедурным, переход в объектам – это переход на один уровень абстракции выше. Парадоксально, но новичкам на первых порах довольно сложно перейти к мышлению в рамках реальных объектов при написании кода. Но освоив объектно-ориентированное программирование, вы, несомненно, останетесь довольны, потому что его мощь позволит вам создавать сложные программы значительно быстрее. Мы же со своей стороны постараемся на примерах доходчиво объяснить, что такое класс, и как его использовать. Приступим.
Что такое класс?
В объектно-ориентированном программировании (ООП) – класс это основной элемент, в рамках которого осуществляется конструирование программ. Класс содержит в себе данные и код, который управляет этими данными.
Класс зачастую описывает объект реального мира. Как и реальный объект, класс содержит свой набор параметров и характеристик. Каждый такой параметр называется поле класса (очень похоже на обычные переменные). Также класс способен манипулировать своими характеристиками (полями) с помощью методов класса (похожи на функции в процедурных языках). Рассмотрим такой объект, как автомобиль.
Оговоримся, что данная статья исключительно для начинающих. В ней не рассматривается наследование, абстрактные классы и т.д.
Создание класса
Что имеет автомобиль? В частности, это:
Напишем класс Car (автомобиль) на C# (аналогично на Java):
Объектно-ориентированное программирование: на пальцах
Статья не мальчика, но мужа.
Настало время серьёзных тем: сегодня расскажем про объектно-ориентированное программирование, или ООП. Это тема для продвинутого уровня разработки, и мы хотим, чтобы вы его постигли.
Из этого термина можно сделать вывод, что ООП — это такой подход к программированию, где на первом месте стоят объекты. На самом деле там всё немного сложнее, но мы до этого ещё доберёмся. Для начала поговорим про ООП вообще и разберём, с чего оно начинается.
Обычное программирование (процедурное)
Чаще всего под обычным понимают процедурное программирование, в основе которого — процедуры и функции. Функция — это мини-программа, которая получает на вход какие-то данные, что-то делает внутри себя и может отдавать какие-то данные в результате вычислений. Представьте, что это такой конвейер, который упакован в коробочку.
Например, в интернет-магазине может быть функция «Проверить email». Она получает на вход какой-то текст, сопоставляет со своими правилами и выдаёт ответ: это правильный электронный адрес или нет. Если правильный, то true, если нет — то false.
Функции полезны, когда нужно упаковать много команд в одну. Например, проверка электронного адреса может состоять из одной проверки на регулярные выражения, а может содержать множество команд: запросы в словари, проверку по базам спамеров и даже сопоставление с уже известными электронными адресами. В функцию можно упаковать любой комбайн из действий и потом просто вызывать их все одним движением.
Что не так с процедурным программированием
Процедурное программирование идеально работает в простых программах, где все задачи можно решить, грубо говоря, десятком функций. Функции аккуратно вложены друг в друга, взаимодействуют друг с другом, можно передать данные из одной функции в другую.
Например, вы пишете функцию «Зарегистрировать пользователя интернет-магазина». Внутри неё вам нужно проверить его электронный адрес. Вы вызываете функцию «Проверить email» внутри функции «Зарегистрировать пользователя», и в зависимости от ответа функции вы либо регистрируете пользователя, либо выводите ошибку. И у вас эта функция встречается ещё в десяти местах. Функции как бы переплетены.
Тут приходит продакт-менеджер и говорит: «Хочу, чтобы пользователь точно знал, в чём ошибка при вводе электронного адреса». Теперь вам нужно научить функцию выдавать не просто true — false, а ещё и код ошибки: например, если в адресе опечатка, то код 01, если адрес спамерский — код 02 и так далее. Это несложно реализовать.
Вы залезаете внутрь этой функции и меняете её поведение: теперь она вместо true — false выдаёт код ошибки, а если ошибки нет — пишет «ОК».
И тут ваш код ломается: все десять мест, которые ожидали от проверяльщика true или false, теперь получают «ОК» и из-за этого ломаются.
Задача, конечно, решаемая за час-другой.
Но теперь представьте, что у вас этих функций — сотни. И изменений в них нужно делать десятки в день. И каждое изменение, как правило, заставляет функции вести себя более сложным образом и выдавать более сложный результат. И каждое изменение в одном месте ломает три других места. В итоге у вас будут нарождаться десятки клонированных функций, в которых вы сначала будете разбираться, а потом уже нет.
Это называется спагетти-код, и для борьбы с ним как раз придумали объектно-ориентированное программирование.
Объектно-ориентированное программирование
Основная задача ООП — сделать сложный код проще. Для этого программу разбивают на независимые блоки, которые мы называем объектами.
Объект — это не какая-то космическая сущность. Это всего лишь набор данных и функций — таких же, как в традиционном функциональном программировании. Можно представить, что просто взяли кусок программы и положили его в коробку и закрыли крышку. Вот эта коробка с крышками — это объект.
Программисты договорились, что данные внутри объекта будут называться свойствами, а функции — методами. Но это просто слова, по сути это те же переменные и функции.
Объект можно представить как независимый электроприбор у вас на кухне. Чайник кипятит воду, плита греет, блендер взбивает, мясорубка делает фарш. Внутри каждого устройства куча всего: моторы, контроллеры, кнопки, пружины, предохранители — но вы о них не думаете. Вы нажимаете кнопки на панели каждого прибора, и он делает то, что от него ожидается. И благодаря совместной работе этих приборов у вас получается ужин.
Объекты характеризуются четырьмя словами: инкапсуляция, абстракция, наследование и полиморфизм. Если интересно, что это такое, приглашаем в кат:
Инкапсуляция — объект независим: каждый объект устроен так, что нужные для него данные живут внутри этого объекта, а не где-то снаружи в программе. Например, если у меня есть объект «Пользователь», то у меня в нём будут все данные о пользователе: и имя, и адрес, и всё остальное. И в нём же будут методы «Проверить адрес» или «Подписать на рассылку».
Абстракция — у объекта есть «интерфейс»: у объекта есть методы и свойства, к которым мы можем обратиться извне этого объекта. Так же, как мы можем нажать кнопку на блендере. У блендера есть много всего внутри, что заставляет его работать, но на главной панели есть только кнопка. Вот эта кнопка и есть абстрактный интерфейс.
Например, над магазином работают два программиста: один пишет модуль заказа, а второй — модуль доставки. У первого в объекте «заказ» есть метод «отменить». И вот второму нужно из-за доставки отменить заказ. И он спокойно пишет: «заказ.отменить()». Ему неважно, как другой программист будет реализовывать отмену: какие он отправит письма, что запишет в базу данных, какие выведет предупреждения.
Наследование — способность к копированию. ООП позволяет создавать много объектов по образу и подобию другого объекта. Это позволяет не копипастить код по двести раз, а один раз нормально написать и потом много раз использовать.
Например, у вас может быть некий идеальный объект «Пользователь»: в нём вы прописываете всё, что может происходить с пользователем. У вас могут быть свойства: имя, возраст, адрес, номер карты. И могут быть методы «Дать скидку», «Проверить заказ», «Найти заказы», «Позвонить».
На основе этого идеального пользователя вы можете создать реального «Покупателя Ивана». У него при создании будут все свойства и методы, которые вы задали у идеального покупателя, плюс могут быть какие-то свои, если захотите.
Идеальные объекты программисты называют классами.
Полиморфизм — единый язык общения. В ООП важно, чтобы все объекты общались друг с другом на понятном им языке. И если у разных объектов есть метод «Удалить», то он должен делать именно это и писаться везде одинаково. Нельзя, чтобы у одного объекта это было «Удалить», а у другого «Стереть».
При этом внутри объекта методы могут быть реализованы по-разному. Например, удалить товар — это выдать предупреждение, а потом пометить товар в базе данных как удалённый. А удалить пользователя — это отменить его покупки, отписать от рассылки и заархивировать историю его покупок. События разные, но для программиста это неважно. У него просто есть метод «Удалить()», и он ему доверяет.
Такой подход позволяет программировать каждый модуль независимо от остальных. Главное — заранее продумать, как модули будут общаться друг с другом и по каким правилам. При таком подходе вы можете улучшить работу одного модуля, не затрагивая остальные — для всей программы неважно, что внутри каждого блока, если правила работы с ним остались прежними.
Плюсы и минусы ООП
У объектно-ориентированного программирования много плюсов, и именно поэтому этот подход использует большинство современных программистов.
А теперь про минусы:
Что дальше
Впереди нас ждёт разговор о классах, объектах и всём остальном важном в ООП. Крепитесь, будет интересно!