День восемьсот восемьдесят восьмой. #TypesAndLanguages
4. Проблема Алмаза. Начало
Проблема Алмаза, иногда называемая Смертельным Алмазом Смерти, возникает, когда мы наследуем одно и то же через несколько базовых сущностей. Если вы думаете, что «проблема есть в C++, но её не существует в Java или C#», то вы слишком сосредотачиваетесь на технической части.
Наследование
Обычно мы говорим, что в Java или C# существует одиночное наследование и множественная реализация интерфейсов. Это правда, но за этим скрывается гораздо более широкая картина.
Наследование позволяет наследовать характеристики и функции от базовой сущности (в большинстве случаев от класса или объекта). Есть много вещей, которые мы можем унаследовать, или много уровней наследования:
1. Наследование сигнатуры
В интерфейсе объявлен метод, мы наследуем его и предоставляем реализацию. Сигнатура здесь означает, что это только «заголовок» метода, без тела. Важно понимать, что эта «сигнатура наследования» не обязательно должна совпадать с «сигнатурой вызова». Например, вы не можете изменить тип возвращаемого значения при реализации интерфейса в C#, но тип возвращаемого значения не является частью «сигнатуры вызова». Java допускает это, но это детали реализации. Когда мы говорим о «наследовании сигнатуры», мы имеем в виду только заголовок метода, который мы получаем от базовой сущности.
2. Наследование реализации
При наследовании реализации мы получаем не только сигнатуру, но и всё тело метода. Это не так давно стало доступно в Java или C# через реализации интерфейса по умолчанию. Это можно рассматривать как типажи (traits). И хотя между наследованием реализации и трейтами есть некоторые различия, они довольно близки друг к другу.
3. Наследование состояния
Это наследование полей. При наследовании состояния мы получаем поле из базовой сущности, которое мы можем использовать в подклассе. В некоторой степени это похоже на примеси (mixins). Также стоит отметить, что у нас может быть наследование состояния без наследования реализации, но в большинстве случаев эти два аспекта объединяются.
4. Наследование идентичности
Можно считать «наследованием конструктора» (не вдаваясь в теорию типов). Разница между миксином и наследованием от класса сводится к конструктору. Вы можете создать экземпляр и получить новую идентичность. Обычно мы получаем идентичность, создавая базовую сущность и «удерживая» её внутри подобъекта.
Наследование в C# и Java
C++ имеет множественное наследование и не делает различий между классом и интерфейсом. В C# и Java запрещено всё, кроме наследования сигнатур. Однако важно понимать, что утверждение, что «в C# и Java не существует множественного наследования», неверно. Существует множественное наследование для сигнатур и одиночное наследование для всего остального.
Однако позже создатели языков поняли, что это может быть не лучшая идея, и была добавлена реализация интерфейса по умолчанию, которая по сути является «наследованием реализации».
Продолжение следует…
Источник: https://blog.adamfurmanek.pl/2021/02/06/types-and-programming-languages-part-4/
Post #1087
1.65K