Быстрое введение в ООП и понятное объяснение его терминов, на примере видеоигр.
Самая важная парадигма программирования в геймдеве сейчас — объектно-ориентированное программирование (далее ООП). Вообще, сообщество программистов можно поделить на несколько лагерей мнений о парадигмах. И если взять пару из них, то первые — будут за ООП, вторые — против. Но всё-же, если ты хочешь стать игровым программистом — без ООП тебе не обойтись, это требование к разработчикам в вакансиях студий.
В этой статье я не буду что-то объяснять способом большинства книг посвящённых ООП (банковскими счетами и т.п.). Все примеры будут приведены в форме игры, или из реальной жизни. Что-бы понять некоторые примеры и термины, лучше знать какой-нибудь ооп язык программирования.
Объектно-ориентированные языки определяют следующими концепциями: наследование, инкапсуляция и полиморфизм. Следственно, если язык программирования не обладает хоть одной из данных концепций — он не считается объектно-ориентированным.
Всё объектно-ориентированное программирование строится из объектов и классов ( которые в свою очередь подразделяются на интерфейсы, абстрактные классы и т.п., но в этой статье речь о них идти не будет). Всё как в реальном мире: человек — объект, собака — тоже объект, и т.д., этот список можно продолжать до бесконечности. Каждый объект состоит из атрибутов и поведения.
Объекты — это строительные блоки объектно-ориентированных программ. Та или иная программа, которая задействует объектно-ориентированную технологию, по сути является набором объектов. В качестве наглядного примера рассмотрим игру, GTA V online (так будет легче привести примеры), содержащую объекты, которые представляют собой игроков. Каждый из этих объектов состоит из данных и поведений.
Данные, содержащиеся в объекте, представляют его состояние. В терминологии объектно-ориентированного программирования эти данные называются атрибутами. В нашем примере, атрибутами игрока могут быть никнейм, баланс, пол и т. д. Атрибуты включают информацию, которая разнится от одного объекта к другому (ими в данном случае являются игроки).
Поведение объекта представляет то, что он может сделать. В процедурных языках поведение определяется процедурами, функциями и подпрограммами. В терминологии объектно-ориентированного программирования поведения объектов содержатся в методах, а вызов метода осуществляется путем отправки ему сообщения. Примите по внимание, что в нашем примере с игроками одно из необходимых поведений объекта Player заключается в задании и возврате значений различных атрибутов. Таким образом, у каждого атрибута будут иметься соответствующие методы, например setGender() и getGender(). В данном случае, когда другому объекту потребуется такая информация, он сможет отправить сообщение объекту Player и узнать значение его атрибута gender.
Методы, в начале которых стоят приставки get и set — называются геттерами и сеттерами соответственно.
В .NET-методиках (например, C#) геттеры и сеттеры считаются свойствами
самих данных. Независимо от используемого подхода цель одна и та же — управляемый доступ к атрибуту.
Если говорить просто, то класс — это «чертеж» объекта. При создании экземпляра объекта вы станете использовать класс как основу для того, как этот объект будет создаваться. Фактически попытка объяснить классы и объекты подобна стремлению решить дилемму «что было раньше — курица или яйцо?». Трудно описать класс без использования термина «объект» и наоборот. В случае с объектно-ориентированным программным обеспечением, в отличие от дилеммы «что было раньше — курица или яйцо?», мы знаем, что первым был именно класс. Нельзя создать экземпляр объекта без класса.
Рассмотрим пример с реальной жизни — калькулятор. Когда вы нажимаете кнопки на нём, чтобы вывести квадрат числа, вы, как правило, не задумываетесь как же калькулятор проведёт эти расчёты — вам нужен только их результат. Так, когда к объекту Player обращается другой объект, например методом getPos(), чтобы получить его координаты в игровом мире, ему не важно откуда объект Player получает эти координаты, ему нужен только ответ на сообщение (в данном случае — getPos), в виде координат игркоа.
…может означать скрытие внутренней реализации от других компонентов. Например, доступ к скрытой переменной может предоставляться не напрямую, а с помощью методов для чтения (геттер) и изменения (сеттер) её значения.
Представьте себе класс Cat. Можно провести альтернативу с реальной жизнью — семейство кошачьих. В ооп возможно наследование одних классов от других. Представим ещё классы Manul и Tiger. Если оба эти класса наследуются от Car, то они будут наследовать его поведение и атрибуты (кроме помеченных специальными ключевыми словами). Но вся прелесть в том — что мы может добавить в классы Manul и Tiger дополнительные атрибуты и поведение. Например у класса Tiger — увеличить массу и размер, а у Manul увеличить значение агрессивности. Вы также можете создавать объекты классов Manul и Tiger.
Полиморфизм — это греческое слово, буквально означающее множественность
форм. Несмотря на то что полиморфизм тесно связан с наследованием, он часто
упоминается отдельно от него как одно из наиболее весомых преимуществ
объектно-ориентированных технологий. Если потребуется отправить сообщение
объекту, он должен располагать методом, определенным для ответа на это сообщение. В иерархии наследования все производные классы наследуют от своих базовых классов — однако, поскольку каждый подкласс представляет собой отдельную сущность, каждому из них может потребоваться дать отдельный ответ на одно и то же сообщение.
Возьмём класс Shape, у которого будет не реализованный метод Draw(). Согласитесь, у каждого производного класса от Shape должна быть разная реализация метода Draw(): у Cube одна, у Circle другая, и т.д. Вы должны указать конкретную форму. Для этого потребуется обеспечить фактическую реализацию в Circle и Cube. Несмотря на то что Shape содержит метод Draw, Circle переопределит этот метод и обеспечит собственный метод Draw(). Переопределение, в сущности, означает замену реализации базового класса на реализацию из производного класса. Давайте в классе shape определим метод getArea(), но оставим его без реализации. Теперь, в Circle нужно реализовать этот метод следующим образом: area = 3.14 * (radius * radius), когда как в Cube: area = length * width.
Итак, полиморфизм имеет очень короткое, и простое для понимания определение:
полиморфизм — это способность объекта использовать методы производного класса, который не существует на момент создания базового.
Пользователь Habr
Источник цитаты: https://habr.com/ru/post/37576/
Существует ещё как минимум несколько видов классов, интерфейсы, много видов методов в классах, и много-много чего ещё — в мире ООП. Но об этом лучше почитать книги и хороших статей. Всем удачи!