1. Класс как схема для объектов
В первую очередь класс нужен для создания объектов. При объявлении класса мы описываем, какие данные (поля) должен содержать и какие команды (методы) должен выполнять создаваемый объект этого типа. К примеру, класс ниже описывает объекты игрушек с типом Toy
. Каждый из них будет помнить уровень оставшегося заряда в виде числа, уметь его снижать и играть с пользователем:
А вот так этот класс используется для создания объектов:
Здесь класс послужил чертежём, описывающим внутреннее устройство и поведение объектов этого типа (экземпляров класса).
2. Класс как основа схемы для объектов
Представим себе, что мы хотим два вида объектов игрушек с разным поведением в команде play
: например, электро-собаки гавкают во время игры, а электро-кошки мяукают. Создадим два класса (ElectricCat
и ElectricDog
), которые будут отличаться только поведением метода play
. Чтобы не дублировать код работы с зарядом (поле charge и метод spendCharge
), воспользуемся механизмом наследования, указав у новых классов класс Toy
родительским:
В примере класс Toy
послужил основой для других классов, а не сам был схемой для объектов. Чтобы отчётливее увидеть в этом моменте отдельную роль, сделаем класс Toy
абстрактным, чтобы напрямую техничеки запретить создавать объекты этого типа, указав тем самым его предназначение как основы новых типов:
3. Класс как список требований к объектам (полиморфизм)
Использование классов не ограничивается созданием объектов, класс указывают и в качестве типа L-value (т.е. ячейки, в которую кладут значения, например, переменная, поле, параметр и тп). При этом в качестве значения в эту ячейку необязательно класть объект того же самого класса: благодаря полиморфизму подойдёт и другой наследник. На примере наших классов это будет выглядеть так:
Типом параметра здесь выступает класс Toy
, но спокойно передаётся и объект класса наследника. Здесь класс Toy
играет другую роль: будучи типом параметра он разрешает вызвать объявленный в Toy
метод у переданного объекта, но запрещает вызов любого отсутствующего в Toy
метода (даже если таковой будет в классе переданного объекта). При этом из-за возможности переопределять поведение методов в наследниках, неизвестно какая реализация метода будет вызвана, известно только, что этот метод будет присутствовать у переданного объекта.
Класс Toy
в роли типа L-value превратился в список требований к объектам – значению необходимо иметь в наличии необходимые методы и быть наследником этого типа. Чтобы лучше увидеть отличие этой роли от предыдущей, можно сделать класс полностью абстрактным (без полей и только с абстрактными методами), из-за чего у него не будет реализации, которой можно поделиться с наследниками (кроме самой необходимости реализовать абстрактные методы).
Эта роль оказалась настолько важной, что для таких очень абстрактных классов ввели отдельный инструмент в виде интерфейсов с особыми механиками их наследования классами, в терминах джавы – имплементации; но позже в интерфейсы были добавлены и методы с реализацией через модификатор default
.
4. Класс как пространство имён
Хоть Java и объектно-ориентированный язык, на нем все же возможно и процедурное программирование, когда методы вызываются не у объектов, а данные хранятся в глобальных ячейках вместо полей объектов. Это достигается через использование слова static
при объявлении полей и методов:
Для обращения к таким полям и методам объекты класса Utils
не нужны, используется имя класса напрямую:
При этом если нестатическое поле присутствует по экземпляру в каждом объекте класса, то статическое поле сущетвует в единственном экземпляре.
Здесь наш класс никак не участвует в создании объектов, а служит пространством имён для статических полей и методов. То есть, например, внутри одного класса не может быть совпадающих по имени двух статических полей, а внутри разных классов – может; для обращения к статическому классу или методу используется название класса, в котором джаве следует его искать
Итог
Классы в джаве используются не только как схемы для будущих объектов одноимённого типа, но и являются основой для других таковых схем, регламентируют взаимодействие с L-value или служат пространством имён для программирования в процедурном стиле. Надеемся, наша статья помогла вам в этом разобраться и оказалась полезной. Удачи в обучении!
Комментарии