Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Трейты, протоколы, интерфейсы

// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

trait Receiver {
    fn send(&self, message: &str);
}

struct EmailAddress(String);

impl Receiver for EmailAddress {
    fn send(&self, message: &str) {
        println!("Email to {}: {}", self.0, message);
    }
}

struct ChatId {
    uuid: [u8; 16],
}

impl Receiver for ChatId {
    fn send(&self, message: &str) {
        println!("Chat message sent to {:?}: {}", self.uuid, message);
    }
}
  • Концепция полиморфизма и обобщений в Rust во многом построена вокруг трейтов.

  • Трейты — это требования к типу в обобщённом контексте.

  • Такие требования работают почти как утиная типизация, проверяемая на этапе компиляции.

    Утиная типизация — понятие из практики динамических нетипизированных языков вроде Python: «если оно ходит как утка и крякает как утка, то это утка».

    То есть любой тип с методами и полями, которые ожидает функция, — допустимый аргумент для этой функции. Если тип реализует нужные методы, в контексте утиной типизации он считается подходящим.

    Трейты работают как статический механизм утиной типизации: мы задаём поведение, а не тип. При этом мы получаем проверку на этапе компиляции, действительно ли это поведение существует.

  • Или иначе: трейты похожи на наборы утверждений, а реализация трейта для типа — это доказательство того, что тип можно использовать везде, где требуется этот трейт.

    У трейтов есть обязательные методы; реализация этих методов — доказательство того, что тип обладает нужным поведением.

Справка:

  • https://doc.rust-lang.org/reference/items/traits.html