ジェネリックトレイト

トレイトも、型や関数と同じようにジェネリックにできます。トレイトのパラメータ には、使用時に具体的な型が与えられます。たとえば、From<T> トレイトは 型変換を定義するために使われます。

#![allow(unused)]
fn main() {
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub trait From<T>: Sized {
    fn from(value: T) -> Self;
}
}
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug)]
struct Foo(String);

impl From<u32> for Foo {
    fn from(from: u32) -> Foo {
        Foo(format!("Converted from integer: {from}"))
    }
}

impl From<bool> for Foo {
    fn from(from: bool) -> Foo {
        Foo(format!("Converted from bool: {from}"))
    }
}

fn main() {
    let from_int = Foo::from(123);
    let from_bool = Foo::from(true);
    dbg!(from_int);
    dbg!(from_bool);
}
  • From トレイトについてはこのコースの後で扱いますが、その std ドキュメントにある定義 は単純なので、参考のためここに転載しています。

  • トレイトの実装は、考えられるすべての型パラメータを網羅する必要は ありません。ここでは、Foo に対する From<&str> の実装がないため、 Foo::from("hello") はコンパイルできません。

  • ジェネリックトレイトは型を「入力」として受け取る一方、関連型は一種の 「出力」型です。トレイトは、異なる入力型に対して複数の実装を持てます。

  • 実際には、Rust では任意の型 T に対して、マッチするトレイト実装は最大でも 1 つでなければなりません。他のいくつかの言語とは異なり、Rust には 「最も具体的」な一致を選ぶためのヒューリスティックはありません。この サポートを追加するための作業が進められており、これは specialization と呼ばれます。