「TDDBCの課題をRustで実施し、言語仕様を学んでいこう!」というシリーズの記事です。
今までの記事は以下となっています。
[ひとことで言うとこんな記事]
以下を学ぶ事ができます。
[目次]
課題3と課題1,2を見てみると、 「同じメソッド名で拡張しなはれ」 と言っているのが自明であります。
Scalaなんかでは、同じメソッド名だとしても引数が違うものを定義するだけの簡単な作業ですが、 Rustにはオーバーロード機能がございません 。
scalaでの例
def hoge(i: Int){
// 実際の処理
}
def hoge(s: String){
// 実際の処理
}
Rustで同じようなことを記述すると error[E0201]: duplicate definitions with name
と言われてコンパイルエラー です。
今回は、以下のrustのドキュメントを元に "ジェネリクス"を用いた方法 で実装していきたいと思います。
トレイトにジェネリックな引数があると、 毎回ジェネリックな型引数の具体的な型を変更してある型に対して複数回実装できるということです。
実際のコードは以下です
※後日パターン不備で、bugfixあげてます is_connected_to パターン不備 #4
range.rs
// 自身しか関わらないもの
pub trait SelfRange {
fn new(lower: i8, upper: i8) -> Self;
fn to_string(&self) -> String;
fn contains(&self, number: i8) -> bool;
}
// 他のstructが絡むもの
pub trait MultiRange<T> {
fn equals(&self, range: &T) -> bool;
fn is_connected_to(&self, range: &T) -> bool;
}
closed_range.rs
// 他のStructが絡む部分の実装
impl MultiRange<OpenRange> for ClosedRange {
fn equals(&self, _: &OpenRange) -> bool {
false
}
fn is_connected_to(&self, range: &OpenRange) -> bool {
match range {
r if self.lower < r.upper && r.upper < self.upper => true,
r if self.lower < r.lower && r.lower < self.upper => true,
_ => false,
}
}
}
impl MultiRange<ClosedRange> for ClosedRange {
fn equals(&self, closed_range: &ClosedRange) -> bool {
self.lower == closed_range.lower && self.upper == closed_range.upper
}
fn is_connected_to(&self, range: &ClosedRange) -> bool {
match range {
r if self.lower <= r.upper && r.upper <= self.upper => true,
r if self.lower <= r.lower && r.lower <= self.upper => true,
_ => false,
}
}
}
上記のように、equals()
とis_connected_to
に関して、引数が OpenRange.ver と ClosedRange.ver 共に実装することが可能となっています。
課題3:閉区間と開区間 by h0ng0yut0 · Pull Request #3 · h0ng0yut0/tddbc-rust-practice
今回は、ジェネリクスとその利用方法、またその1例としてのオーバーロード を学べました。次回の課題は何が学べるのか楽しみです。
[これから読んでみたい本]
__一緒に様々なことを学んでいく仲間を募集__しています。
このサイトのお問い合わせなどからご連絡いただけると幸いです。