Технологии программирования
Лекция 4. Основы ООП. Наследование. Интерфейсы
Объектно-ориентированное программирование (ООП) основывается на четырех основных принципах: абстракция, инкапсуляция, наследование и полиморфизм.
-
Абстракция — это выделение основных характеристик объекта, которые наиболее важны в контексте задачи. Она позволяет сосредоточиться на основных свойствах объекта, не вдаваясь в детали его реализации.
-
Инкапсуляция — это принцип, согласно которому детали реализации объекта скрыты от пользователя. Это позволяет упростить работу с объектом, так как пользователю не нужно знать детали его реализации, а только то, как с ним работать.
-
Наследование — это механизм, который позволяет создавать новые типы объектов на основе уже существующих. Новый тип наследует все свойства и методы старого, и может добавлять свои собственные свойства и методы.
-
Полиморфизм — это свойство системы, позволяющее использовать один и тот же интерфейс для работы с объектами разных типов. Это позволяет сделать код более универсальным и легко адаптируемым к новым условиям.
Наследование
Наследование в Java позволяет создавать новые классы на основе существующих, таким образом повторно используя код и упрощая разработку.
Наследование в Java обозначается ключевым словом extends. Класс-потомок должен всегда указывать своего родителя, даже если тот не определяет никаких методов или свойств.
Переопределение методов осуществляется с помощью ключевого слова @override. При этом метод в классе-потомке должен иметь такую же сигнатуру, как и метод в родительском классе.
Вот пример наследования для классов Animal, Cat и Dog, где метод sayHello переопределяется в каждом классе:
public class Animal {
public void sayHello() {
System.out.println("Hello from Animal!");
}
}
public class Cat extends Animal {
@Override
public void sayHello() {
System.out.println("Hello from Cat!");
}
}
public class Dog extends Animal {
@Override
public void sayHello() {
System.out.println("Hello from Dog!");
}
}
Пример использования этих классов:
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.sayHello(); // вывод: "Hello from Cat!"
Dog dog = new Dog();
dog.sayHello(); // вывод: "Hello from Dog!"
}
}
Полиморфизм в java
Полиморфизм в Java реализуется через механизм наследования и переопределения методов. Рассмотрим пример:
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.makeSound(); // Output: "Animal sound"
Cat cat = new Cat();
cat.makeSound(); // Output: "Meow!"
var animals = listOf(animal, cat);
for (var animal : animals) {
animal.sayHello;
}
}
}
В этом примере метод makeSound переопределен в классе Cat, поэтому при вызове этого метода для объекта типа Cat будет выполнен метод из этого класса, а для объекта типа Animal - метод из родительского класса. Это и есть реализация полиморфизма в Java.
Класс, объявленный как final, не может быть унаследован другими классами. Это означает, что если вы создаете класс и хотите, чтобы он был базовым и не мог изменяться, вы можете объявить его как final. Это помогает предотвратить случайную модификацию базовых классов, что может привести к непредвиденным последствиям.
Ключевое слово super
В Java ключевое слово super используется для обращения к членам родительского класса. Оно может быть использовано в методах и конструкторах подкласса.
Вот пример использования ключевого слова super в конструкторе класса Java на примере классов Animal и Dog:
public class Animal {
String name;
Animal(String name) {
this.name = name;
System.out.println(this.name + " created.");
}
void move() {
System.out.println(name + " is moving.");
}
}
public class Dog extends Animal {
Dog(String name) {
super(name);
System.out.println(name + " as a puppy created.");
}
@Override
void move() {
System.out.println(name + " is running.");
super.move();
}
public static void main(String[] args) {
Dog dog = new Dog("Rex");
dog.move();
}
}
Интерфейсы
В Java запрещено множественное наследование, так как это может привести к конфликтам имен методов и полей, а также к неоднозначности вызовов методов. В таких случаях компилятор не сможет определить, какой метод следует вызвать. Кроме того, множественное наследование может усложнить понимание и поддержку кода, так как становится сложнее отслеживать, какие методы и поля принадлежат каждому из суперклассов.
Вместо множественного наследования в Java используется концепция интерфейсов, которые позволяют определить набор методов без необходимости наследования класса.
Интерфейсы в Java - это особый тип данных, который определяет набор методов, но не реализует их. Интерфейсы используются для определения поведения объекта, не привязываясь к его реализации. Это делает код более гибким и расширяемым.
public interface Animal {
void makeSound();
}
public interface Swimmer {
void swim();
}
public class Dolphin implements Animal, Swimmer {
@Override
public void makeSound() {
// sound of a dolphin
}
@Override
public void swim() {
// dolphin swimming
}
}