Динамическое и статическое связывание
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Struchkov Mark 2024-10-05 07:28:51 +03:00
parent 46e423c2db
commit 953e4534c6
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
5 changed files with 344 additions and 3 deletions

View File

@ -1,5 +1,6 @@
--- ---
aliases: aliases:
- полиморфизмом
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-09-27 date: 2024-09-27
@ -11,7 +12,7 @@ linked:
--- ---
Полиморфизм — это один из фундаментальных принципов [[ООП|объектно-ориентированного программирования]] (ООП), который позволяет объектам разных классов обрабатывать одно и то же сообщение (вызов метода) по-разному. Это делает код более гибким и расширяемым, упрощая добавление новых возможностей без изменения существующего кода. Полиморфизм — это один из фундаментальных принципов [[ООП|объектно-ориентированного программирования]] (ООП), который позволяет объектам разных классов обрабатывать одно и то же сообщение (вызов метода) по-разному. Это делает код более гибким и расширяемым, упрощая добавление новых возможностей без изменения существующего кода.
## Основные виды полиморфизма ## Основные виды полиморфизма
**Полиморфизм времени компиляции (статический)**: Это форма полиморфизма, которая определяется на этапе компиляции программы. Примеры включают **перегрузку методов** и **перегрузку операторов**. Полиморфизм времени компиляции ([[../other/Статическое связывание|статическое связывание]]): Это форма полиморфизма, которая определяется на этапе компиляции программы. Примеры включают перегрузку методов и перегрузку операторов.
Один и тот же метод может иметь несколько версий, которые различаются по количеству или типам параметров. Один и тот же метод может иметь несколько версий, которые различаются по количеству или типам параметров.
@ -28,7 +29,7 @@ linked:
} }
``` ```
**Полиморфизм времени выполнения (динамический)**: Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется **наследование** и **переопределение методов**. Полиморфизм времени выполнения ([[../other/Динамическое связывание|динамическое связывание]]): Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется наследование и переопределение методов.
Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов. Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов.

View File

@ -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<Animal> 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]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -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]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -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]]
**Автор**::
### Дополнительные материалы
- [[Статическое связывание]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Динамическое связывание в Java]]
<!-- SerializedQuery END -->

View File

@ -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]]
**Автор**::
### Дополнительные материалы
- [[Динамическое связывание]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Статическое связывание в Java]]
<!-- SerializedQuery END -->