Почему в Rust нет наследования?
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct Id {
pub id: u32
}
impl Id {
// методы
}
// 🔨❌, в Rust нет наследования!
pub struct Data: Id {
// Унаследованное поле "id"
pub name: String,
}
impl Data {
// методы, но также включает методы Id или, возможно, переопределения
// этих методов.
}
// ✅
pub struct Data {
pub id: Id,
pub name: String,
}
impl Data {
// Все методы data, которые не относятся к трейтам.
}
impl SomeTrait for Data {
// Реализации трейтов в отдельных блоках impl.
}
-
У наследования есть ряд недостатков.
-
Разнородность по умолчанию:
Наследование классов неявно позволяет использовать типы разных классов взаимозаменяемо, при этом нельзя явно указать конкретный тип или то, совпадает ли один тип с другим.
Для таких операций, как равенство или сравнение, это допускает сравнение и проверку равенства, которые выбрасывают ошибку или иным образом вызывают панику.
-
Несколько источников истины о том, из чего состоит структура данных и как она себя ведёт:
Поля типа скрыты иерархией наследования.
Методы типа могут переопределять методы родительского типа или переопределяться дочерним типом. В сложных кодовых базах, которые поддерживают несколько сторон, трудно понять, каково поведение типа.
-
Динамическая диспетчеризация по умолчанию добавляет накладные расходы на поиск в vtable:
Чтобы динамическая диспетчеризация работала, нужно место, где хранятся сведения о том, какие методы вызывать, и другая информация о типе, известная во время выполнения.
Это хранилище и есть
vtableзначения. Вызовы методов требуют больше разыменований, чем вызов метода для типа, известного на этапе компиляции.