ブランケットトレイト実装
トレイトがローカルであれば、好きなだけ多くの型に対して実装できます。これをどこまで進められるでしょうか?
// 著作権 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait PrettyPrint { fn pretty_print(&self); } // ブランケット実装です! 何かが Display を実装していれば、 // PrettyPrint も実装していることになります。 impl<T> PrettyPrint for T where T: std::fmt::Display, { fn pretty_print(&self) { println!("{self}") } }
-
トレイトの定義箇所では、トレイト実装の対象は何でもかまわず、境界のない
Tも含まれます。何も分からない
Tに対しては何もできないため、これは一般的ではありません。 -
条件付きブランケット実装は、はるかに有用で、見かけたり自分で書いたりする機会も多いでしょう。
こうした実装では、
impl <T: Display> ToString for T {...}のように、トレイトに境界が付きます。上の例では、Display を実装するすべての型に対するブランケット実装があります。この実装がトレイト境界から利用できる情報は 1 つで、
Display::fmtを実装していることです。これは、コンソールに整形表示する実装を書くには十分です。
-
ただし、この種の実装には注意してください。結果として、下流のユーザーがより意味のある実装を行えなくなる可能性があります。
上の例を
Debug向けに書いていないのは、そうするとほとんどすべての型がPrettyPrintを実装することになってしまうからです。また、Debugは意味的にDisplayと似ていません。Debugは、より人間が読みやすいものではなく、デバッグ出力を目的としています。
参照:
- https://doc.rust-lang.org/reference/glossary.html#blanket-implementation