Как стать автором
Обновить
188.1
Beget
Beget — международный облачный провайдер

ООП для кота – моделируем кота через классы

Время на прочтение5 мин
Количество просмотров3.7K


Программирование — довольно сложная штука, и, поэтому, его хорошо учить на наглядных примерах.

А что может быть наглядней котофея? :-)) Поэтому, попробуем рассмотреть кота через объектно-ориентированное программирование (ООП) и его классы.

Итак, что же представляет собой кот с точки зрения ООП?

Статья, в большей степени, будет интересна начинающим.

Что такое классы в ООП и зачем они?

Но, для начала, давайте поймём, что скрывается за понятием класса в рамках ООП (это поможет нам понять ту информацию, которая будет ниже).

Если сказать упрощённо, то класс — это такой своеобразный шаблон, по которому создаются объекты определённого типа.

Класс может иметь определённые поля, например, если это класс «человек», то он может иметь такие поля как: возраст, рост, пол, и т.д.

Кроме полей, класс может иметь определенные методы, описывающие поведение его объектов. Например, человек может ходить, говорить, спать на диване (вместо работы (:-) и т.д.

Если сказать более обобщённо, то класс нужен, для упаковки данных и некой логики в рамках одного компонента; также, подобная компоновка позволяет реализовать многократное использование кода.

Скажем, в примере выше, мы можем создать много людей, с одним и тем же поведением, которые вместо того, чтобы ходить на работу, будут желать только лежать на диване и ничего не делать :-)

Также, методы и поля класса имеют так называемые «модификаторы доступа», которые показывают, кому доступны для просмотра и использования поля и методы класса.

Среди модификаторов доступа можно назвать такие как:

  • public: он показывает, что доступ возможен всем другим классам;
  • private: используется для скрытия реализации, чтобы внешние пользователи не могли сломать логику.
Здесь можно отметить такой интересный момент, что для доступа к скрытым полям и методам могут быть использованы такие конструкции как «геттеры» и «сеттеры» (их мы ещё увидим наглядно ниже) — которые позволяют получить что-то или установить что-то, безопасным способом.

Например, возраст человека может быть вычислен каким-то способом, недоступным снаружи, но сам результат вычислений, — собственно число, символизирующее возраст — можно сделать доступным по запросу, с помощью «геттера».

В теории, что могло бы быть, если бы возраст человека был доступен для изменения любому: например, его максимальное значение 100, а кто угодно мог бы его поставить на 100500 (что вряд ли похоже на правду), кроме того, мы совершенно не знаем, кто и где это сделал…

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

Кроме того, как уже было сказано, они дают безопасность, реализуя «инкапсуляцию» — один из базовых принципов ООП (своими данными должен управлять сам объект).

Также, неотъемлемым элементом понятия класса является понятие «конструктора» — специального метода, который вызывается во время создания объекта и служит для того, чтобы поля объекта были проинициализированы, а сам объект был создан в корректном состоянии (например, у обычного человека не может быть 4 ноги, и у него обязательно должно быть имя).

При этом, имя конструктора должно совпадать с именем класса, он не будет иметь никаких возвращаемых значений, и у класса может быть несколько конструкторов с разным количеством параметров (мы можем создать только человека с именем, человека с именем и возрастом и т.д.).

Итак, после того, как мы немножко ознакомились с понятием классов, попробуем спроектировать свой собственный класс Cat.

Generation Next Cat

Предположим, что наш кот будет иметь три ключевые характеристики (которые и будут представлять собой поля класса):

  • как зовут кота (nickname);
  • уровень его усталости или, если хотите, энергичности (power);
  • настроение (feeling).
Как мы выше говорили, классу нужен конструктор, и мы создадим конструктор для генерации кота, где ему сразу передадим имя (String nickname), а также проинициализируем и другие поля:



Разберём код выше: как можно видеть, мы снабдили все три переменные — имя, энергетику и настроение кота модификаторами private, то есть они недоступны извне класса.

Прямо под ними можно видеть конструктор класса, с передаваемым ему именем, и инициализацией других полей.

И вот тут, кстати, у наблюдательных читателей, наверняка возникнет вопрос: а почему мы передаём только имя (String nickname) в конструктор? По идее, мы должны были в скобках передавать все три поля?

Абсолютно верно, можно было передавать все три поля в скобках, но тут был выбран вариант попроще, так как имя является обязательным, в то время как остальные два поля уже имеют значения по умолчанию и, при создании новых котов, просто можно их называть, давая имя, в то время как остальные параметры «пускай остаются по умолчанию».

Таким образом:

  • всё передавать в скобках конструктору следует, если не существует значений по умолчанию, поля обязательны и требуется некая пользовательская конфигурация для всех полей;
  • в противовес первому варианту, некоторые поля можно оставить внутри конструктора, не передавая в скобках, если они редко меняются, и есть для них значения по умолчанию.
Говоря про конструктор, возникает интересный вопрос, а что было бы, если бы мы не определяли конструктор в явном виде?

Очень просто: java сама создаст пустой конструктор по умолчанию, где все поля останутся равными null или 0 (что для кота будет явным багом — " абстрактный кот в вакууме" нам не интересен, нам нужен только «конкретно этот рыжий Барсик»).

Теперь, ещё один любопытный момент: как можно видеть в коде выше, в конструкторе все три поля имеют спереди ключевое слово this с точкой в конце.

Что это значит: это ссылка на текущий объект класса. То есть, мы здесь говорим (через точку), что текущему объекту класса будут присваиваться поля.

А можно ли обойтись без этого ключевого слова this?

Можно и так, но, только в том случае, если имя поля и параметр, передаваемый в скобках, не совпадают по названию:



Что это означает, если написать «человеческими словами»: «при создании объекта, полю nickname — присвоить ту строку, которую передаст пользователь».

Тем не менее, так делать не рекомендуется, так как это не очень наглядно и использование ключевого слова this выглядит более понятным.

Также, создадим несколько методов, которые характеризует кота:

  • он сможет мурлыкать (purr());
  • спать определённое количество часов и восстанавливать за счёт этого свои силы (sleep(into hours));
  • изменять своё настроение в зависимости от восстановленных сил (updateFeeling()).
Ещё создадим несколько геттеров, с помощью которых можно будет получать значения полей этого класса:
  • getNickname();
  • getPower();
  • getFeeling();
Выше мы упомянули то, что у кота может меняться настроение, в зависимости от энергии (т.е. количества сил) — перечислим все возможные варианты его настроений в специальном классе java — enum, который позволяет хранить константные значения.

Применение такого класса более безопасно, чем явное задание их с помощью, например, строк, так как, например, легко можно допустить опечатку.

Посмотрим, что у нас получилось:



Кстати говоря, многие знают класс enum только как средство хранения константных значений, однако, что, если я скажу вам, что в нём можно хранить ещё и методы (и не только — об этом ниже), чтобы наши константы могли что-либо делать?

Например, пускай эмоции выводят смайлики и тогда это будет выглядеть вот так:



Как можно видеть, рядом с константами в скобках находятся параметры. В качестве таких параметров можно передавать:

  • Строки;
  • Числа;
  • Объекты.
При этом, нужно помнить, что тип параметра должен соответствовать, тому, который объявлен в конструкторе enum (в нашем примере это строка):



А использовать такие методы можно, например, следующим образом:



К слову, как вы могли догадаться, раз здесь в коде enum присутствует конструктор, то никто не мешает нам создать несколько полей, например, типа: int, string и объявить их в конструкторе!

Таким образом, можно передавать уже не один параметр, а несколько!

Что это даёт: у нас образуется своеобразная небольшая база данных, к которой можно обращаться и забирать оттуда информацию:



Использовать хранящиеся данные можно следующим образом:



Ну и напоследок, попробуем смоделировать поведение кота, в разных ситуациях, при этом, избежав множественных циклов if-else, для чего используем паттерн «Состояние»: создадим ряд классов, реализующих общий интерфейс и переопределяющих его методы — каждый класс по-своему:



Как можно видеть, в двух кусках кода выше используются сеттеры, которых у нас изначально не было:



— их нужно добавить в основной код кота, чтобы не было ошибки:

Теги:
Хабы:
+14
Комментарии11

Публикации

Информация

Сайт
beget.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия