RustにはC++やJavaのような特別なコンストラクタがありません。通常、コンストラクタは関連関数(例えば、new)として実装されます。重要な特徴は以下の通りです。
::を使って呼び出されます。Result<Self, E>を返すことができ、エラーが発生する可能性があるコンストラクタに便利です。with_capacity、from_str、カスタムバリエーションなど、さまざまなファクトリーを実装できます。基本的なコンストラクタの例は以下の通りです。
struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Point { x, y } } }
エラーが発生する可能性があるコンストラクタの例は以下の通りです。
impl Point { pub fn try_new(x: i32, y: i32) -> Result<Self, String> { if x < 0 || y < 0 { Err("Coordinates must be non-negative".to_string()) } else { Ok(Point { x, y }) } } }
コンストラクタには通常の関数、メソッド、または関連関数のどれを使うべきか、その理由は?
多くの人は「メソッド」と答えます。しかしRustではコンストラクタは関連関数のみ(selfなし)でなければなりません。なぜなら、インスタンスがまだ存在しないので通常のメソッドを呼び出すことはできません。
struct Foo; impl Foo { // 関連関数、メソッドではない pub fn new() -> Self { Foo } }
物語
プログラマーがメソッドとしてコンストラクタを実装しました:
impl Point { pub fn make(&self, x: i32, y: i32) -> Self { ... } }これは不合理で混乱を招きます:オブジェクトを作成するためには、まだ存在しないオブジェクトが必要だからです!開発者はこのメソッドをどう呼び出すか迷いました。静的関数に修正されました。
物語
古典的なエラー:警告なしにfallibleコンストラクタのためにOption<Self>を返し、その結果として連鎖的なエラーを見逃すことがありました。Result<Self, E>を返すようにしたことで、エラーをより明示的に表示できるようになりました。
物語
from_parts、from_strの形式のファクトリーをFrom/FromStrトレイトを使用せずに実装しました。その結果、標準の変換メカニズム(例えば、str.parse::<MyType>())が機能しませんでした。エラーを発見した後、FromStrを導入し、エコシステムのライブラリとの互換性を向上させました。