Динамическое и статическое связывание
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
46e423c2db
commit
953e4534c6
@ -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/Динамическое связывание|динамическое связывание]]): Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется наследование и переопределение методов.
|
||||||
|
|
||||||
Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов.
|
Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов.
|
||||||
|
|
||||||
|
224
dev/java/Динамическое связывание в Java.md
Normal file
224
dev/java/Динамическое связывание в Java.md
Normal 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) -->
|
||||||
|
|
55
dev/java/Статическое связывание в Java.md
Normal file
55
dev/java/Статическое связывание в Java.md
Normal 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) -->
|
||||||
|
|
32
dev/other/Динамическое связывание.md
Normal file
32
dev/other/Динамическое связывание.md
Normal 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 -->
|
||||||
|
|
29
dev/other/Статическое связывание.md
Normal file
29
dev/other/Статическое связывание.md
Normal 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 -->
|
||||||
|
|
Loading…
Reference in New Issue
Block a user