1.42M
Категория: ПрограммированиеПрограммирование

Классы. ООП

1.

КЛАССЫ И ОБЪЕКТЫ

2.

Знакомство с основами ООП в Java
Объектно-ориентированное
программирование
(ООП) — это описание объектов реального мира
средствами выбранного языка программирования с
организацией их поведения и взаимодействия.
Например: представим объект – мяч. Он обладает
следующими свойствами – диаметр, цвет, материал
(резина, кожа), назначение (теннисный, волейбольный и
т.д.) Мяч может лежать, катиться, прыгать, летать – таким
образом, можно сделать вывод, что есть некий шаблон, с
помощью которого можно описать мяч. Этим шаблоном и
выступает класс.
Класс — шаблон, в котором описаны общие черты и
действия объекта (объектов).
Объект — экземпляр класса, обладающий уже
конкретными свойствами и поведением.

3.

Экземпляр класса
В
ООП
свойства
будущего
объекта
описываются полями, а поведение — методами .
Класс
определяется
с
помощью
ключевого
слова сlass (имя класса пишется с заглавной буквы):
В данном случае класс называется Student. После
названия класса идут фигурные скобки, между которыми
помещается тело класса.

4.

В теле класса как раз и помещаются поля и методы.
Добавим, для начала поля:

5.

Классы и методы
Методы, как и поля, помещаются между двумя
фигурными скобками класса, т.е. в его теле. Добавим один
из методов:
Таким образом,
класс это — поля и
методы по работе с
ними, которые, в
итоге, представляют
собой
шаблон
будущего объекта.
В классе Student
два поля: name
представляет имя студента, а age — его возраст. Также
добавлен метод printInfo, который ничего не возвращает
(void) и просто выводит эти данные в консоль.

6.

Если
сейчас
запустить
программу, то в
консоли ничего не
будет. Это и не
удивительно,
ведь
определён
лишь
шаблон,
но
не
создано ни одного
объекта. Т.е. класс не
использован,
не
реализован.
Для реализации
класса доработаем
нашу программу:

7.

Объект вроде и создан, но программа снова ничего не
выводит. Дело в том, что класс — это тоже тип данных. В
методе main определена переменная bob, которая
представляет класс Student. Но пока эта переменная не
указывает ни на какой объект и, по умолчанию, она имеет
значение null. По большому счету мы ее пока не можем
использовать, поэтому вначале необходимо создать объект
класса Student. А мы пока определили лишь пустую
переменную.
Ещё одно замечание. Классы в Java определяются в
разных файлах. В данном случае, для простоты, два класса
помещены в одном файле. «Главный» класс, содержащий
метод main, должен иметь модификатор public (в
представленном случае это класс — Program), а сам файл
кода должен называться по имени этого класса, то есть, в
данном случае, файл должен называться Program.java. В
Вашем случае файл может называться по-другому,
следовательно и «главный» одноимённый класс будет иным.

8.

Выделение памяти под объект
Класс — ссылочный тип данных. Это означает, что каждый
новый экземпляр должен ссылаться на определённый адрес в
оперативной памяти, где для каждого из его членов (поля и
методы) выделяется место. С нашей стороны экземпляру
было дано имя. Но место в памяти под него не выделялось.
Для ссылочного типа данных память выделяется с помощью
оператора new:

9.

Объекту, с
именем bob, была
выделена память
под его поля и
методы. Полям были
присвоены значения,
впоследствии
выведенные на
экран.
Для выделения
памяти в классе
вызывается конструк
тор, который пока
явно задействован
не был.

10.

Классы и конструкторы
Конструктор это специальный
метод, имеющий тоже название,
что и класс. И вызывается
конструктор всегда, когда создаётся
новый объект (экземпляр класса).
Если в классе не был определен
конструктор, то для этого класса
автоматически
создается
конструктор
без
параметров.
Проверим это. Добавим в класс
пустой конструктор с выводом
информации о его вызове (см. рис.)
В выводе мы увидим, что, не
смотря на добавления объекта bill,
конструктор был вызван лишь один
раз:
Call of constructor!
Name: Bob
Age: 19

11.

С помощью оператора new выделим память под объект bill:
Вывод в консоль
изменился:
Call of constructor!
Name: Bob
Age: 19
Call of constructor!
Пример хорошо
иллюстрирует процесс:
1. Выделена память
под bob (Call of constructor);
2. Заполнены
поля name и age с вызовом
метода printInfo();
3. Выделена память
под bill (Call of constructor).

12.

Итак, конструктор — это тоже метод, но имеющий два отличия:
1. Конструктор ничего не возвращает, он лишь выделяет память под
создаваемый объект;
2. Конструктор имеет тоже имя, что и класс.
Следовательно, определяя конструктор мы не указываем тип
возвращаемого значения (даже void писать не обязательно).

13.

Параметры
конструкторов
Но если конструктор является методом,
значит для него действует правило перегрузки
(overloading). Следовательно, конструкторов
может быть несколько. И отличаться они будут
типом и числом параметров. В нашем классе
уже есть один конструктор без параметров.
Добавим ещё один — с двумя параметрами
newName и newAge (см. пример).
В консоли теперь будет следующий вывод:
Call of constructor without parameters!
Name: Bob
Age: 19
Call of constructor with parameters!
Name: Bill
Age: 22
Сначала был вызван пустой конструктор
без параметров. Затем полям созданного
объекта были присвоены значения (см. строки:
5-7 выше) и выведены в консоль (строка: 8).
Затем (в строках: 9-10) был вызван конструктор
с параметрами (т.е. с одновременной
инициализацией полей), и метод, выводящий
в консоль значения данных полей.

14.

Классы и инициализаторы
Кроме
конструктора
полям
объекта
можно
присваивать
значения
с
помощью
инициализатора
объекта.
Инициализатор
выполняется
раньше любого из конструкторов и в
нём помещается код, общий для
всех конструкторов (см. пример).
Вывод будет следующим:
Call of constructor without
parameters!
Name: Bob
Age: 19
Call of constructor with parameters!
Name: Bill
Age: 22
Call of constructor without
parameters!
Name: Noname
Age: 0

15.

Как видно, конструктор без параметров всё равно был вызван. Значения
полей, даже если и не были заданы, были заимствованы у инициализатора —
метода класса: с телом, но без имени.
В данном разделе были изучены базовые понятия ООП: принципы
создания классов и обязательные операции при работе с объектами (при
реализации классов).
• Классы, представляя собой прототип будущего объекта,
содержат поля и методы.
• Конструктор не только выделяет память под объект, но и производит
инициализацию полей.
• Инициализатор задаёт значения полей класса по умолчанию.

16.

ПАКЕТЫ

17.

Объединение в наборы
Классы в Java классы объединяются в пакеты, которые
являются, своего рода логической структурой. Если
сравнивать с реальным миром, то классы — это
инструменты. А инструменты, как правило распределяют
по их видам. Вот простой пример (рис. 1)
Рис. 2. Методы класса Math пакета Java.lang
Рис. 1. Виды инструментов
Разумеется, в java уже включён свой набор
встроенных пакетов. С некоторыми из них мы уже успели
поработать: java.util, например. Пакет содержит набор
классов, а каждый класс включает в себя определённое
количество методов. Пример ниже демонстрирует
пакет java.lang, и один из его классов Math, включающего
набор математических методов (рис. 2)
Над серьёзной программой работают разные
разработчики, которые могут называть свои классы
одинаковыми именами. Принадлежность к пакету
позволяет гарантировано избежать конфликта имен между
классами (Рис. 3).
Рис. 3. Преимущества использования
пакетов

18.

Получается,
что
самая
минимальная
программа на java должна иметь класс,
содержащий главный метод main. И этот класс
обязательно должен принадлежать пакету. Во
всех вновь созданных проектах на java пакет
(package) автоматически создаётся средой
разработки (см. пример)
Получается, что в составе проекта, нужно:
• создать отдельную папку с именем пакета;
• создать файл с именем класса и поместить в эту папку.
В случае с проектом выше среда разработки сама создала папку first, а в ней
разместила файл с именем Program.java.
Имена пакетов записываются, как
правило, с маленькой буквы. Для того,
чтобы лучше понять принцип работы с
пакетами
создадим
проект
под
названием, например, package_test:
При этом, обратите внимание, что
при создании главного класса, ему было
дано имя Program.

19.

Когда мы работаем в среде программирования
(NetBeans, например), то в левой части можем видеть
навигатор, отражающий структуру проекта. Тут видно, что
Program.java находится внутри пакета package_test.
Добавим новый пакет, который назовём foreaders (для читателей), в котором создадим
класс Book. Для того, чтобы создать новый пакет необходимо правой кнопкой мыши
кликнуть по элементу Source Packages и выбрать пункт контекстного меню «Java
Package…«:

20.

Среди пакетов теперь можно увидеть созданный foreaders. Теперь правой кнопкой
мыши необходимо кликнуть на него и создать в нём новый класс Book:

21.

«Наполним» созданный класс Book минимальным содержанием:

22.

В методе main() класса Programm (пакет: package_test) вызовем класс Book
(пакет: foreaders) и реализуем его:

23.

Пакеты, встроенные в Java и их вызов
Директива import указывает на
имя подключаемого класса (в
данном случае класса Scanner).
В примерах выше подключался
один класс: Book из созданного
нами
пакета,
Scanner
из
вcтроенного пакета. Но встроенный
пакет java.util содержит не только
класс Scanner.
Чтобы не подключать по отдельности каждый класс, можно сразу подключить
все классы пакета (пакет целиком):
Также класс Scanner может быть подключён с использованием полного пути:

24.

Указание полного пути как раз и позволяет одновременно использовать классы с одинаковым
именем, но принадлежащих разным пакетам. Например, класс Date имеется как в пакете java.util,
так и в пакете java.sql:
Статические члены класса будут рассмотрены позже. Пока достаточно сказать, что
использование статического члена класса не требует создания объекта. Например
класс Math содержит большое количество математических методов и все они статические. При
подключении
таких
классов
производится
статический
импорт.
Вместе
с
директивой import используется модификатор static:
Статический
импорт
позволил
использовать методы без названия класса.
Например, писать не Math.cos(radian),
а cos(radian), не Math.PI (число Пи), а
просто PI. Благодаря статическому импорту
System
стала
возможны
запись: out.printf(«%.2f\n», result).
Классы из пакета java.lang (например,
String)
подключаются
в
программу
автоматически. Их нет необходимости
импортировать.

25.

Можно подвести итог:
• каждый проект на языке Java использует пакеты — отдельные модули
(пространство имен), которым соответствует одноименный каталог (папка);
• пакет содержит библиотеки (группы) классов;
• количество классов в пакете неограниченно;
• пакеты могут иметь разнообразные уровни вложения (подкаталоги,
подпапки);
• на разных уровнях вложения пакетов имена могут повторяться.

26.

МОДИФИКАТОРЫ ДОСТУПА

27.

В Java используются следующие модификаторы доступа:
• public: публичный, общедоступный класс (или член класса), поля и методы
которого видны другим классам: как из текущего пакета, так и из внешних
пакетов;
• private: закрытый класс (или член класса), доступность к которым
обеспечивается только внутри него самого (из других классов, а тем более,
пакетов, доступа/видимости нет);
• protected: доступность к классу или его члену обеспечивается из любого
места в текущем классе или пакете, или в производных классах, даже если они
находятся в других пакетах;
• модификатор по умолчанию: применяется, если модификатор для метода
и/или поля указан не был, — такие поля или методы видны всем классам
в текущем пакете.

28.

Обратимся к классу Student и применим разные модификаторы к его полям
и методам:

29.

Реализация в main() будет выглядеть следующим образом:

30.

Следующим шагом поместим класс Student в отдельный файл. Для этого
кликнем правой кнопкой мыши на имя пакета (в нашем случай это modifiers) и
выберем «Java Class…»:
В качестве имени класса укажем — Student:

31.

Теперь можно «вырезать» (Ctrl + X) код класса Student и вставить в
созданный файл класса «Student.java»:
Файл с главным классом и методом main() оставляем без изменений. Вывод
должен остаться прежним, но теперь каждый класс расположен в отдельном
файле.

32.

Модификаторы и
инкапсуляция
данных
Под инкапсуляцией (англ.
encapsulation

капсулирование, помещение в
оболочку)
понимается
ограничение
доступа
к
методам и полям класса.
Например,
ограничение
прямого
доступа
к
переменной (полю) age в
классе
Student
позволит
избежать присвоения ему
отрицательного
значения.
Присвоение значения можно
организовать,
например,
через метод, с проверкой не
отрицательности
значения.
Изменим
описание
класса Student (поменяем
модификатор age с protected н
а private) и добавим два
метода: получение значения
возраста (getAge) и его
присвоения (setAge):

33.

Информация о возрасте теперь защищена от случайных изменений. К полю age больше нельзя обращаться
напрямую. Теперь за это отвечают методы:
getAge() — получение данных о возрасте;
setAge(int newAge) — задание значения нового возраста (при помощи параметра newAge) с защитой от ввода
отрицательных значений.
Подобные методы получили название геттеров (от слова get — получить) и сеттеров (от слова set — задать). Их
названия, в основном, содержат префиксы get или set + названия поля, за которое они отвечают.
В реализации класса также будут изменения:

34.

Подытоживая рассмотрение уровней видимости членов класса, можно представить их
в виде таблицы, в которой наглядно отражено «сужение» доступа от public к private:
Распределение доступа с использованием различных модификаторов
Таким образом, с помощью модификаторов доступа, в процессе работы программы,
предотвращается присвоение полям класса некорректных значений, либо скрываются
некоторые данные (инкапсуляция). При подобном сокрытии отсутствует возможность
обращения к таким данным напрямую: при выводе на консоль или при других операциях.
Т.е. без особых методов невозможно даже узнать значение конкретного поля класса

35.

СТАТИЧЕСКИЕ ЧЛЕНЫ КЛАССА
И КЛЮЧЕВОЕ СЛОВО THIS

36.

Статические члены класса это его методы или свойства, к которым можно обратиться не создавая объект
(экземпляр) данного класса.
Модификатор static
С ключевым словам static вероятнее всего вы знакомы с начала изучения Java. Главный класс программы
содержит метод main, который является статическим: public static void main(String[] args).
Модификатора static (англ. статичный) — делает поле или метод класса «независимыми» от объекта.
Например: System.out.println («Это статический метод!«) — как раз пример вызова статического метода.
Для чего нужны статические поля или методы класса? Самый простой пример — счётчик созданных объектов.
Допустим есть класс Car (Автомобиль):

37.

В main() создадим два объекта и удостоверимся, что они посчитаны:
Под каждый объект в динамической памяти
выделяется место:

38.

Модификатор static в Java означает привязку именно к классу, а не объекту. Если
поле статично, значит к нему можно обращаться, используя имя класса. Аналогично и с
методами. Как можно видеть из примера выше, поле count статично в классе Car.
Значит обращение к данному полю возможно запросом вида: Car.count. Но если
модификатор у поля — private, то обращение осуществляется с помощью метода с
модификатором public.
Под статические члены класса в оперативной памяти, начиная с Java 8.0,
предназначена отдельная статическая область — Metaspace. В рассматриваемом
случае статическое поле counter является общим для всех создаваемых объектов.
Инкремент counter-а в конструкторе позволяет подсчитать создаваемые объекты.
При описании статических полей класса необходимо выполнение как минимум
двух правил:
• статические переменные должны быть объявлены вне всякого метода;
• статические переменные могут быть инициализированы при их объявлении или
блоком кода, отмеченного ключевым словом static.

39.

Ключевое слово this
В Java определено ключевое слово this чтобы метод ссылался на вызвавший его объект:
• this может использоваться внутри любого метода для ссылки на текущий объект;
• this можно использовать везде, где допускается ссылка на объект текущего класса.
В основном this используется в двух случаях:
1. Когда у переменной экземпляра класса и переменной метода/конструктора одинаковые
имена;
2. Когда нужно вызвать конструктор одного типа (например, конструктор по умолчанию или
параметризированный) из другого. Это еще называется явным вызовом конструктора.
Рассмотрим первый пример — класс Person, когда у переменной экземпляра и метода
одинаковые имена.

40.

Как видно из примера выше проблема в том, что две переменные называются
одинаково. Первая (String name) является полем класса Private, а вторая (String name)
принадлежит конструктору. Поэтому виртуальная машина Java (Java Virtual Machine —
JVM) «не понимает«, какой из переменных выражении:
name = name;
и что присваивается. Соответственно, JVM выбирает ту, которая встречается раньше
(т.е. параметр конструктора в строке 4):
Получается, что в конструкторе значение поля name присваивается само себе, что
совершенно бесполезно и бессмысленно. Использование ключевого слова this, в
данном случае, укажет, что вызывается поле класса Person, а не переменная метода:

41.

Т.е., как и было отмечено, this сошлётся на вызвавший объект. И, в итоге, для данного объекта, имя
персоны в конструкторе присвоится согласно параметру конструктора.
Во втором примере this будет использован для явного вызова конструктора. Такой способ может
пригодиться когда конструкторов несколько и для каждого из них не нужно будет переписывать код
инициализации полей:
Таким образом, в коде
конструктору
с
двумя
параметрами, как будто
указывается:
• вызови this (этот)
конструктор,
который
имеет один параметр;
• инициализируй
недостающую
переменную.
Аналогичная ситуация и
для конструктора с тремя
параметрами.

42.

Как видно, в основном, ключевое слово this в Java используется в составе методов,
или конструкторов экземпляра класса.
В неявном виде this передается во все методы, кроме статических. Именно
поэтому this часто называют неявным параметром.
Вывод: this может быть использован для обращения к объекту, вызвавшему метод.
English     Русский Правила