ジェネリックトレイト
トレイトも、型や関数と同じようにジェネリックにできます。トレイトのパラメータ には、使用時に具体的な型が与えられます。たとえば、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 と呼ばれます。