Тема, которая касается полиморфизма в java обычно довольно тяжело дается начинающим программистам, однако игнорировать ее прост не возможно т.к. она является одной из базовых тем в java. Так что же все таки собой являет полиморфизм в java? Если говорить “человеческим языком” в контексте java, то полиморфизм — это возможность одного объекта принимать различную типизацию, или соответствовать различным типам. Что имеется ввиду? Давайте посмотрим на примере, который довольно просто покажет, что же такое полиморфизм в java.
За основу нашего примера полиморфизма будет взят класс Human, у которого будут 2 поля — имя и возраст, а так же минимальный набор конструкторов, геттеров и сеттеров и метод toString() для человекоподобного отображения нашего объекта в консоли.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class Human { private String name; private int age; public Human() { } public Human(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } } |
А теперь создадим интерфейс Singer у которого будет абстрактный метод sing(), а также интерфейс Runner у которого будет оглашен абстрактный метод run().
Целиком этот код будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public class Main { public static void main(String[] args) { } } class Human { private String name; private int age; public Human() { } public Human(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } } interface Singer{ void sing(); } interface Runner{ void run(); } |
А теперь попробуем имплементировать интерфейс Singer нашему Human. Сразу же станет необходимым определить метод sing() внутри нашего Human и описать его логику.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
public class Main { public static void main(String[] args) { } } class Human implements Singer { private String name; private int age; public Human() { } public Human(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } //!!!!!!!!!!!!!!!!!!!!!! implementation @Override public void sing() { System.out.println("sing " + this.name + " eeeee"); } } interface Singer { void sing(); } interface Runner { void run(); } |
Теперь начнется самое интересное. Поскольку мы реализовали интерфейс Singer в нашем Human, это позволят экземпляру (объекту) класса Human дополнительно принимать обличие типа Singer. Но почему? Все потому, что при реализации интерфейса, он обязывает нас реализовать все его абстрактные методы, и именно это является единственным критерием соответствия типу Singer (ну или любому другому интерфейсу… все зависит от ситуации). А это означает, что если мы соответствуем какому-либо типу, мы можем принять его типизацию.
1 2 3 4 5 6 7 8 9 |
public class Main { public static void main(String[] args) { Human human = new Human("vasya", 31); Singer singer = human; } } |
Но на этом еще не все. Давайте реализуем еще один интерфейс в нашем Human. Тогда наш класс будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
class Human implements Singer, Runner { private String name; private int age; public Human() { } public Human(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\'' + ", age=" + age + '}'; } //!!!!!!!!!!!!!!!!!!!!!! implementation @Override public void sing() { System.out.println("sing " + this.name + " eeeee"); } @Override public void run() { System.out.println("run as fast as i can"); } } |
Как видим появился новый метод run(), который мы были вынуждены реализовать поскольку иплементировали интерфейс Runner. Что же мы получим в конце?
1 2 3 4 5 6 7 8 9 10 |
public class Main { public static void main(String[] args) { Human human = new Human("vasya", 31); Singer singer = human; Runner runner = human; } } |
Как видно, теперь наш объект human типа Human, имеет возможность быть типом Singer , а так же Runnable. Иными словами у нашего объекта теперь есть много видов типизации…т.е. “поли типизация”, в свою очередь тип — это форма (морф от греческого), или, другими словами, как выглядит наш объект, соответственно “поли типизацию” можем переназвать на …..(барабанная дробь) – полиморфизм.