1.34M
Category: programmingprogramming

Основные принципы ООП. Углубленное изучение ООП, наследование, полиморфизм

1.

JAVA
Урок #4: Основные принципы ООП.
Углубленное изучение ООП, наследование,
полиморфизм. Разбор практических
примеров применения ООП при разработке
приложений. Внутренние классы.
Интерфейсы. Множественная реализация.
www.andersenlab.com

2.

План урока
• Что такое наследование и зачем нужно
• Примеры наследования
• Модификаторы доступа с учетом наследования
• Абстрактные классы и методы
• Рассмотрим несколько сложных примеров ООП
• Внутренние классы
• Интерфейсы
• Множественная реализация
• Отличия интерфейса от абстрактного класса
2

3.

Несколько очень похожих классов
public class Cat {
private String name;
private String color;
private int age;
public class Dog {
private String name;
private String color;
private int age;
public Cat(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public void info() {
System.out.println("name: " + name + "
color: " + color + " age: " + age);
}
}
public Cat(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public void info() {
System.out.println("name: " + name + "
color: " + color + " age: " + age);
}
}
И допустим что у нас есть еще пачка похожих классов животных:
Cow, Horse, Duck, Chicken, …
Можно ли как-то сократить такой код?
3

4.

Наследование
public class Animal {
protected String name;
protected String color;
protected int age;
Создаем так называемый
родительский класс (суперкласс)
Animal
public Animal(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public void info() {
System.out.println("name: " + name +
" color: " + color + " age: " + age);
}
Пока код не намного короче…
}
4

5.

Посмотрим теперь на животных
public class Cat extends Animal {
public Cat(String name, String color, int age) {
super(name, color, age);
}
}
public class Duck extends Animal {
public Duck(String name, String color, int age) {
super(name, color, age);
}
}
public class Dog extends Animal {
public Dog(String name, String color, int age) {
super(name, color, age);
}
}
public class Chicken extends Animal {
public Chicken(String name, String color, int age) {
super(name, color, age);
}
}
public class Horse extends Animal {
public Horse(String name, String color, int age) {
super(name, color, age);
}
}
public class Pig extends Animal {
public Pig(String name, String color, int age) {
super(name, color, age);
}
}
Довольно много классов уместилось на одной странице
5

6.

Возможный вариант наследования
Object
Animal
Cat
Dog
DogType1
Horse
DogType2
6

7.

Недопустимый вариант наследования
Object
Animal
CatType1
CatType2
CatType3
Множественное наследование не поддерживается
7

8.

Модификаторы доступа
private
Модификатор
отсутствует
(default/package)
protected
public
Один и тот же класс
+
+
+
+
Подкласс, производный от класса из того же самого
пакета
-
+
+
+
Класс из того же самого пакета, не являющийся
подклассом
-
+
+
+
Подкласс, производный от класса другого пакета
-
-
+
+
Класс из другого пакета, не являющийся подклассом,
производный от класса данного пакета
-
-
-
+
8

9.

Абстрактные классы и методы
Особенности:
• Нельзя создать экземпляр абстрактного
класса;
public abstract class Animal {
private String name;
Абстрактные методы – методы не
имеющие тела, каждый наследник должен
переопределить такой метод (например,
конкретную реализацию метода voice() не
имеет смысла прописывать в классе
Animal, поскольку все наследники будут
реализовывать его по-разному)
В абстрактном классе могут быть обычные
методы;
В обычном классе не может быть
абстрактных методов.
public abstract void voice();
public void info() {
System.out.println("name: " + name);
}
}
9

10.

Коты и тарелки – пример применения ООП
public class Cat {
private String name;
private int appetite;
public Cat(String name, int appetite) {
this.name = name;
this.appetite = appetite;
}
public void eat() {
}
}
Постановка задачи: программа должна
уметь создавать котов и тарелки с едой. В
тарелке имеется какое-то количество еды.
Кот должен уметь кушать еду из тарелок в
соответствии со своим аппетитом.
Сделаем набросок кода:
Пока у нас есть отдельно коты, и отдельно
тарелки
public class Plate {
private int food;
public Plate(int food) {
this.food = food;
}
public void info() {
System.out.println("Food amount: " + food);
}
}
10

11.

Коты и тарелки – пример применения ООП
Давайте считать что в котах и тарелках мы
объявили геттеры и сеттеры. Тогда код
кормежки кота может выглядеть вот так.
public class MainClass {
public static void main(String[] args) {
Cat barsik = new Cat("Barsik", 5);
Plate plate = new Plate(100);
plate.info();
barsik.eat();
plate.setFood(plate.getFood() barsik.getAppetite());
}
}
Мы задаем тарелке количество еды равное
количеству еды, которое там было, минус
аппетит кота.
Работать будет, но подход не очень хороший.
11

12.

Коты и тарелки – пример применения ООП
public class Plate {
private int food;
Добавим тарелке поведение (метод
decreaseFood(int amount)): в тарелке
может уменьшаться количество еды.
То есть вызывая у тарелки метод
decreaseFood(5) вы должны указать то
количество еду, которое надо “убрать” из
тарелки.
// геттеры/сеттеры
public Plate(int food) {
this.food = food;
}
public void decreaseFood(int amount) {
food -= amount;
}
public void info() {
System.out.println("Food amount: " + food);
}
}
12

13.

Коты и тарелки – пример применения ООП
• Теперь модифицируем метод eat() в классе
public class Cat {
private String name;
private int appetite;
// геттеры/сеттеры
public Cat(String name, int appetite) {
this.name = name;
this.appetite = appetite;
}
public void eat(Plate p) {
p.decreaseFood(appetite);
}
}
Cat.
• Когда мы просим кота поесть, необходимо
указать на тарелку из которой он должен
кушать, для этого в качестве аргумента
прокидываем в метод eat(Plate plate)
ссылку на объект типа Plate.
• Во время выполнения метода eat() мы
считаем что в тарелке должно
уменьшиться количество еды, в
зависимости от аппетита кота (так как он
эту еду съест). Поэтому обращаемся к
тарелке и вызываем у нее метод
decreaseFood(передавая
сюда аппетит кота).
13

14.

Коты и тарелки – пример применения ООП
• Собрали все воедино
public class MainClass {
public static void main(String[] args) {
Cat barsik = new Cat("Barsik", 5);
Plate plate = new Plate(100);
plate.info();
barsik.eat(plate);
plate.info();
}
}
Результат:
Food amount: 100
Food amount: 95
• Создали кота Барсика с аппетитом 5
• Создали тарелку plate, в которой лежит 100
ед. еды
• Просим отпечатать информацию о тарелке
• Просим Барсика покушать из тарелки plate
• Смотрим как изменилась
тарелка
14

15.

Внутренние классы
public class Student {
private int studentId;
private String name;
private int group;
private String faculty;
private String city;
private String street;
private int houseId;
private int flatId;
private String email;
private String skype;
private long phoneNumber;
// constructors, methods
}
Пусть изначально описание класса
Student представлено в виде:
В описании класса можно целый
набор данных объединить под
общим именем Address и выделить
его как внутренний класс.
Класс Student станет более
коротким и понятным.
15

16.

Внутренние классы
public class Student {
private int studentId;
private String name;
private int group;
private String faculty;
private Address address;
// может быть private, protected
public class Address { // внутренний класс
private String city;
private String street;
private int houseId;
private int flatId;
private String email;
private String skype;
private long phoneNumber;
// методы внутреннего класса
}
}
Внешний и внутренний классы могут
выглядеть в итоге так:
Внутренний класс может быть использован
любым членом своего внешнего класса, а
может и не использоваться вовсе, хотя в
этом случае утрачивается его смысл.
Использование объекта внутреннего класса
вне своего внешнего класса возможно
только при наличии доступа (видимости) и
при объявлении ссылки в виде:
Student.Address address =
new Student().new Address();
16

17.

Внутренние классы - наследование
public class SubStudent extends Student {
// code
public class SubAddress extends Address
{
// code
}
}
Наследование от внешнего и внутреннего
классов
Если внутренний класс наследуется обычным
образом другим классом
(после extends указываетс:
ИмяВнешнегоКласса.ИмяВнутреннегоКласса), то
он теряет доступ к полям своего внешнего
класса, в котором был объявлен.
public class FreeAddress extends Student.Address
{
public FreeAddress() {
new Student().super();
}
public FreeAddress(Student student) {
student.super();
}
}
Наследование от внутреннего класса
В данном случае конструктор класса FreeAddress
должен объявлять объект класса Student или
получать его в виде параметра, что позволит
получить доступ к ссылке на
внутренний класс Address,
наследуемый классом FreeAddress.
17

18.

Внутренние классы
public class Student {
private int studentId;
private String name;
private int group;
private String faculty;
private Address address;
// может быть private, protected
public class Address { // внутренний класс
private String city;
private String street;
private int houseId;
private int flatId;
private String email;
private String skype;
private long phoneNumber;
// методы внутреннего класса
}
}
Внешний и внутренний классы могут
выглядеть в итоге так:
Внутренний класс может быть использован
любым членом своего внешнего класса, а
может и не использоваться вовсе, хотя в
этом случае утрачивается его смысл.
Использование объекта внутреннего класса
вне своего внешнего класса возможно
только при наличии доступа (видимости) и
при объявлении ссылки в виде:
Student.Address address =
new Student().new Address();
18

19.

Интерфейсы
Назначение интерфейса — описание или спецификация функциональности,
которую должен реализовывать каждый класс, его имплементирующий. Класс,
реализующий интерфейс, предоставляет к использованию объявленный
интерфейс в виде набора public-методов в полном объеме.
Интерфейсы подобны абстрактным классам, хотя и не являются классами.
[public] interface Name [extends NameOtherInterface,…, NameN] {
// constants, methods
}
19

20.

Интерфейсы
public interface Flyable{
String MOVEMENT = "Flight";
final int SPEED= 123;
public static final int MAX_SPEED= 600;
void fly();
public boolean isAbleToFly();
public abstract String objectType(
String objectName
);
default void isAlive(boolean alive){
if(alive == true) {
System.out.println("It’s a bird!");
} else {
System.out.println("It’s a plane");
}
}
}
Все объявленные в интерфейсе абстрактные
методы
автоматически
трактуются
как
public abstract, а все поля — как public static final,
даже если они так не объявлены.
Интерфейсы
методы.
могут
объявлять
статические
В интерфейсах могут объявляться методы с
реализацией с ключевым словом default. Эти
методы могут быть public или private.
20

21.

Множественная реализация
public class MyPlane implements Flyable{
@Override
public void fly() {
// реализация метода
}
Класс может реализовывать любое число
интерфейсов, указываемых через запятую после
ключевого слова implements, дополняющего
определение класса. После этого класс обязан
реализовать
все
абстрактные
методы,
полученные им от интерфейсов, или объявить
себя абстрактным классом.
@Override
public boolean isAbleToFly() {
// реализация метода
return false; // возвращаемое значение
}
public class MyObject implements Flyable, Rolling,
Floatable, … {
@Override
public String objectType(String objectName) {
// реализация метода
return "Тип объекта - Самолет";
}
}
}
// реализация всех абстрактных методов,
// унаследованных от перечисленных
// интерфейсов
21

22.

Разница между интерфейсом и абстрактным классом
1.
Интерфейс
описывает
только
поведение. У него нет состояния. А у
абстрактного класса состояние есть:
он описывает и то, и другое.
Интерфейс только описывает поведение.
Соответственно, мы не сможем реализовать
внутри интерфейса геттеры и сеттеры. Такова
природа интерфейса: он нужен для работы с
поведением, а не состоянием.
1.
Абстрактный класс связывает между
собой и объединяет классы, имеющие
очень близкую связь. В то же время,
один и тот же интерфейс могут
реализовать
классы,
у
которых
вообще нет ничего общего.
1.
Классы могут реализовывать сколько
угодно интерфейсов, но наследоваться
можно только от одного класса.
Допустим есть интерфейс Flyable, описывающий
возможность полета. Он только описывает
поведение, соответствующее его названию, —
«летающий». Под определение «способный
летать» попадает много объектов, не связанных
между собой (самолеты, птицы, насекомые и
т.п.).
Множественного наследования в Java нет, а
множественная реализация есть.
22

23.

Вопросы по теме . . .
www.andersenlab.com
English     Русский Rules