diff --git a/dev/architecture/Полиморфизм.md b/dev/architecture/Полиморфизм.md index d6c96123..bb444d00 100644 --- a/dev/architecture/Полиморфизм.md +++ b/dev/architecture/Полиморфизм.md @@ -1,5 +1,6 @@ --- -aliases: +aliases: + - полиморфизмом tags: - maturity/🌱 date: 2024-09-27 @@ -11,7 +12,7 @@ linked: --- Полиморфизм — это один из фундаментальных принципов [[ООП|объектно-ориентированного программирования]] (ООП), который позволяет объектам разных классов обрабатывать одно и то же сообщение (вызов метода) по-разному. Это делает код более гибким и расширяемым, упрощая добавление новых возможностей без изменения существующего кода. ## Основные виды полиморфизма -**Полиморфизм времени компиляции (статический)**: Это форма полиморфизма, которая определяется на этапе компиляции программы. Примеры включают **перегрузку методов** и **перегрузку операторов**. +Полиморфизм времени компиляции ([[../other/Статическое связывание|статическое связывание]]): Это форма полиморфизма, которая определяется на этапе компиляции программы. Примеры включают перегрузку методов и перегрузку операторов. Один и тот же метод может иметь несколько версий, которые различаются по количеству или типам параметров. @@ -28,7 +29,7 @@ linked: } ``` -**Полиморфизм времени выполнения (динамический)**: Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется **наследование** и **переопределение методов**. +Полиморфизм времени выполнения ([[../other/Динамическое связывание|динамическое связывание]]): Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется наследование и переопределение методов. Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов. diff --git a/dev/java/Динамическое связывание в Java.md b/dev/java/Динамическое связывание в Java.md new file mode 100644 index 00000000..90ff1dc2 --- /dev/null +++ b/dev/java/Динамическое связывание в Java.md @@ -0,0 +1,224 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2024-10-05 +zero-link: +parents: +linked: +--- +Важной особенностью [[../../../../garden/ru/dev/other/Динамическое связывание|динамического связывания]] в Java является использование **виртуальных методов** — методов, которые могут быть переопределены в наследуемых классах, и выбор нужного метода происходит в зависимости от типа объекта, а не ссылки на него. + +Динамическое связывание в Java обеспечивается [[../../../../knowledge/dev/java/JVM|JVM]] через таблицы виртуальных методов (vtable). Когда создается объект, JVM строит таблицу, содержащую указатели на методы, которые могут быть вызваны для данного объекта. Если метод переопределён в подклассе, JVM заменяет соответствующую запись в таблице. Это позволяет JVM выбрать нужный метод во время выполнения, основываясь на фактическом типе объекта. + +Ключевые шаги, которые выполняет JVM: +1. Когда вызывается метод через ссылку, JVM проверяет vtable для конкретного типа объекта. +2. Если метод был переопределён, ссылка указывает на новый метод в vtable. +3. Это позволяет избежать необходимости решать, какой метод вызывать, на этапе компиляции. + +**Преимущества:** +- **Гибкость.** Позволяет легко реализовывать полиморфизм, давая возможность объектам разных типов обрабатывать вызовы по-разному. +- **Расширяемость.** Классы можно легко расширять или заменять, не изменяя уже существующий код. + +**Недостатки:** +- **Производительность.** Динамическое связывание требует дополнительных вычислительных ресурсов для поиска метода во время выполнения. +- **Сложность отладки.** Ошибки, связанные с динамическим связыванием, могут проявиться только во время выполнения, что усложняет их обнаружение. + +## Примеры динамического связывания в Java +**Переопределение методов (Method Overriding)** +Динамическое связывание чаще всего проявляется при переопределении методов в классах-наследниках. Когда метод базового класса переопределён в подклассе, JVM выбирает метод для вызова во время выполнения, основываясь на фактическом типе объекта. + +```java +class Animal { + void sound() { + System.out.println("Animal makes a sound"); + } +} + +class Dog extends Animal { + @Override + void sound() { + System.out.println("Dog barks"); + } +} + +public class Main { + public static void main(String[] args) { + Animal myAnimal = new Dog(); // Ссылка на Animal, объект Dog + myAnimal.sound(); // Вызывается Dog.sound() благодаря динамическому связыванию + } +} +``` + +**Работа с интерфейсами** +Когда класс реализует интерфейс, метод интерфейса может быть реализован по-разному в каждом классе. JVM динамически выбирает метод во время выполнения в зависимости от типа объекта. + +```java +interface Shape { + void draw(); +} + +class Circle implements Shape { + public void draw() { + System.out.println("Drawing a Circle"); + } +} + +class Square implements Shape { + public void draw() { + System.out.println("Drawing a Square"); + } +} + +public class Main { + public static void main(String[] args) { + Shape myShape = new Circle(); // Ссылка на Shape, объект Circle + myShape.draw(); // Вызывается Circle.draw() благодаря динамическому связыванию + + myShape = new Square(); // Ссылка теперь указывает на объект Square + myShape.draw(); // Вызывается Square.draw() + } +} +``` + +**Абстрактные классы** +Когда у нас есть абстрактные классы с абстрактными методами, конкретные реализации этих методов в подклассах также связаны динамически. Фактический метод выбирается во время выполнения программы. + +```java +abstract class Animal { + abstract void sound(); +} + +class Cat extends Animal { + @Override + void sound() { + System.out.println("Cat meows"); + } +} + +class Lion extends Animal { + @Override + void sound() { + System.out.println("Lion roars"); + } +} + +public class Main { + public static void main(String[] args) { + Animal myAnimal = new Cat(); // Ссылка на Animal, объект Cat + myAnimal.sound(); // Вызывается Cat.sound() благодаря динамическому связыванию + + myAnimal = new Lion(); // Ссылка теперь указывает на объект Lion + myAnimal.sound(); // Вызывается Lion.sound() + } +} +``` + +**Виртуальные методы** + +В Java ==все нестатические методы являются виртуальными по умолчанию, то есть они могут быть переопределены в подклассах и будут динамически связаны на этапе выполнения.== Исключение составляют методы, помеченные как `final`, `private`, или `static`, которые не могут быть переопределены и, соответственно, не требуют динамического связывания. + +```java +class Parent { + void show() { + System.out.println("Parent's show()"); + } +} + +class Child extends Parent { + @Override + void show() { + System.out.println("Child's show()"); + } +} + +public class Main { + public static void main(String[] args) { + Parent obj = new Child(); // Ссылка на Parent, объект Child + obj.show(); // Вызывается Child.show() благодаря динамическому связыванию + } +} +``` + +**Вызов методов через типы-переменные родительского класса** +Когда у нас есть переменная или ссылка на объект базового типа (например, через тип переменной `Object` или `Animal`), которая ссылается на объект производного класса, вызов методов будет зависеть от фактического типа объекта. Это типичный сценарий динамического связывания. + +```java +class Example { + @Override + public String toString() { + return "Example class"; + } +} + +public class Main { + public static void main(String[] args) { + Object obj = new Example(); // Ссылка на Object, объект Example + System.out.println(obj); // Вызывается Example.toString() благодаря динамическому связыванию + } +} +``` + +**Работа с коллекциями и их элементами (включая generics)** +При работе с коллекциями, особенно с элементами типа Object, динамическое связывание происходит при вызове методов объектов, которые содержатся в этих коллекциях. + +```java +import java.util.ArrayList; + +class Animal { + void sound() { + System.out.println("Animal makes a sound"); + } +} + +class Dog extends Animal { + @Override + void sound() { + System.out.println("Dog barks"); + } +} + +public class Main { + public static void main(String[] args) { + ArrayList animals = new ArrayList<>(); + animals.add(new Dog()); // Добавляем объект Dog в коллекцию типа Animal + + for (Animal animal : animals) { + animal.sound(); // Вызывается Dog.sound() благодаря динамическому связыванию + } + } +} +``` + +**Приведение типов** +Когда объект приводится к типу родительского класса или интерфейса, динамическое связывание всё равно продолжает работать. Тип ссылки может быть `Animal`, но если объект фактически является `Dog`, будет вызван метод `Dog`, а не `Animal`. + +```java +class Bird extends Animal { + @Override + void sound() { + System.out.println("Bird sings"); + } +} + +public class Main { + public static void main(String[] args) { + Animal myAnimal = new Bird(); // Ссылка на Animal, объект Bird + myAnimal.sound(); // Вызывается Bird.sound() благодаря динамическому связыванию + } +} +``` + +*** +## Мета информация +**Область**:: [[../../../../garden/ru/meta/zero/00 Java разработка|00 Java разработка]] +**Родитель**:: [[../../../../garden/ru/dev/other/Динамическое связывание|Динамическое связывание]] +**Источник**:: +**Создана**:: [[2024-10-05]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/java/Статическое связывание в Java.md b/dev/java/Статическое связывание в Java.md new file mode 100644 index 00000000..bf08b12c --- /dev/null +++ b/dev/java/Статическое связывание в Java.md @@ -0,0 +1,55 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2024-10-05 +zero-link: +parents: +linked: +--- +Примеры [[../other/Статическое связывание|статического связывания]] в Java + +**Перегрузка методов (Method Overloading).** Когда методы с одним именем имеют разные параметры (тип или количество). Решение о том, какой метод вызвать, принимается на этапе компиляции. + +```java +class Example { + void show(int x) { + System.out.println("Integer: " + x); + } + void show(String s) { + System.out.println("String: " + s); + } +} +``` + +**Методы или поля с ключевым словом** `final` +Методы и поля, помеченные как `final`, подлежат статическому связыванию, так как их реализация не может быть изменена. + +**Методы или поля внутри** `private` **классов** +Методы, объявленные с модификатором доступа `private`, также связываются статически, поскольку они недоступны для переопределения в подклассах. + +**Статические методы (Static Methods)** +Статические методы связаны с классом, а не с объектом. Поэтому их связывание происходит на этапе компиляции. + +**Простые вызовы полей** +Доступ к полям (переменным класса) также осуществляется через статическое связывание. Например, если переменная является примитивным типом или объявлена как `static`, её связывание происходит на этапе компиляции. + +**Перегрузка операторов (Operator Overloading)** +Хотя Java не поддерживает прямую перегрузку операторов, операторы, такие как + для строк, являются примерами статического связывания. Компилятор точно знает, какой оператор будет использован с каким типом данных. + +```java +String result = "Hello" + "World"; // Конкатенация строк +``` +*** +## Мета информация +**Область**:: [[../../../../garden/ru/meta/zero/00 Java разработка|00 Java разработка]] +**Родитель**:: [[../../../../garden/ru/dev/other/Статическое связывание|Статическое связывание]] +**Источник**:: +**Создана**:: [[2024-10-05]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/other/Динамическое связывание.md b/dev/other/Динамическое связывание.md new file mode 100644 index 00000000..61eba466 --- /dev/null +++ b/dev/other/Динамическое связывание.md @@ -0,0 +1,32 @@ +--- +aliases: + - позднее связывание + - динамического связывания +tags: + - maturity/🌱 +date: 2024-10-05 +zero-link: +parents: +linked: +--- +Динамическое связывание, также называемое поздним связыванием, ==происходит на этапе выполнения программы== и позволяет реализовать [[../architecture/Полиморфизм|полиморфизм]]. + +В отличие от [[Статическое связывание|статического связывания]], здесь решение о том, какой метод вызывать, принимается не на этапе компиляции, а во время исполнения программы. + +- [[../java/Динамическое связывание в Java|Динамическое связывание в Java]] +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: [[../architecture/Полиморфизм|Полиморфизм]] +**Источник**:: +**Создана**:: [[2024-10-05]] +**Автор**:: +### Дополнительные материалы +- [[Статическое связывание]] + +### Дочерние заметки + + +- [[Динамическое связывание в Java]] + + diff --git a/dev/other/Статическое связывание.md b/dev/other/Статическое связывание.md new file mode 100644 index 00000000..0ce9bbd8 --- /dev/null +++ b/dev/other/Статическое связывание.md @@ -0,0 +1,29 @@ +--- +aliases: + - статического связывания +tags: + - maturity/🌱 +date: 2024-10-05 +zero-link: +parents: +linked: +--- +Статическое связывание — это процесс связывания, который происходит на этапе компиляции программы и позволят реализовать [[../architecture/Полиморфизм|полиморфизм]]. Это означает, что все ссылки на переменные, методы и другие объекты определяются до начала выполнения программы. В большинстве случаев статическое связывание применяется к обычным методам, перегруженным методам и полям, которые явно определены во время компиляции. + +- [[../java/Статическое связывание в Java|Статическое связывание в Java]] +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: [[../architecture/Полиморфизм|Полиморфизм]] +**Источник**:: +**Создана**:: [[2024-10-05]] +**Автор**:: +### Дополнительные материалы +- [[Динамическое связывание]] + +### Дочерние заметки + + +- [[Статическое связывание в Java]] + +