Rust の視点から見た継承
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // データ pub struct Data { id: usize, name: String, } // 具体的な振る舞い impl Data { fn new(id: usize, name: impl Into<String>) -> Self { Self { id, name: name.into() } } } // 抽象的な振る舞い trait Named { fn name(&self) -> &str; } // 実装された振る舞い impl Named for Data { fn name(&self) -> &str { &self.name } }
-
Rust の視点、つまり継承というものがこれまで存在しなかった視点からすると、 継承を導入することは、型とトレイトの境界を曖昧にするように見えます。
-
型は、具体的なデータと、それに関連付けられた振る舞いです。
トレイトは、型によって実装されなければならない抽象的な振る舞いです。
クラスは、データ、振る舞い、そしてその振る舞いに対するオーバーライドを組み合わせたものです。
-
Rust から来た立場では、継承可能なクラスは、型でもありトレイトでもある もののように見えます。
-
これは利点ではありません。なぜなら、具体的な型について推論できなくなるからです。
-
この 2 つを分離できないと、ジェネリックな振る舞いと具体的な詳細について 考えるのが難しくなります。なぜなら、OOP ではこれら 2 つの概念が 互いに結び付けられているからです。
-
フラットなフィールドアクセスや型定義における DRY の利便性は、 振る舞いとデータを区別して書くコードが持つ明確さを失う代償に 見合うものではありません。