Паттерн newtype
Newtype — обёртка вокруг существующего типа, часто примитивного:
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// Уникальный идентификатор пользователя, реализованный как newtype вокруг `u64`.
pub struct UserId(u64);
В отличие от псевдонимов типов, newtype не взаимозаменяем с оборачиваемым типом:
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct UserId(u64);
fn needs_user(user: UserId) {
// ...
}
fn main() {
needs_user(1); // 🛠️❌
}
Компилятор Rust также не позволит использовать методы или операторы, определённые для базового типа:
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct UserId(u64);
fn main() {
assert_ne!(UserId(1), UserId(2)); // 🛠️❌
}
-
Студенты должны были встретить паттерн newtype на курсе «Основы», когда изучали кортежные структуры.
-
Запустите пример, чтобы показать студентам сообщение об ошибке компилятора.
-
Измените пример так, чтобы использовать псевдоним типа вместо newtype, например
type MessageId = u64. Изменённый пример должен компилироваться, что подчеркнёт различия между двумя подходами. -
Подчеркните, что newtype по умолчанию не имеет связанного с ним поведения. Нужно сознательно решать, какие методы и операторы базового типа вы готовы переадресовывать. В нашем примере
UserIdразумно разрешить сравнениеUserId, но не имеет смысла разрешать арифметические операции вроде сложения или вычитания.