👌
自作構造体にアドホック多相を実装する(Rust)
こちらの記事で紹介されていた内容を自分なりに理解するために簡単に実装してみました。
実装
fn main() {
let p1 = MyPoint(2, 3);
let p2 = MyPoint(3, 4);
let abs = p1.point_poly::<Absolute>(&p2);
let rel = p1.point_poly::<Relative>(&p2);
println!("{:?}", abs); // MyPoint(3, 4)
println!("{:?}", rel); // MyPoint(5, 7)
}
#[derive(Clone, Copy, Debug)]
struct MyPoint(i32, i32);
// define enum as type
enum Absolute {}
enum Relative {}
//----- actual behavior of each type -----
trait PointMethod {
fn point(line: &MyPoint, p: &MyPoint) -> MyPoint;
}
impl PointMethod for Absolute {
fn point(_line: &MyPoint, p: &MyPoint) -> MyPoint {
*p
}
}
impl PointMethod for Relative {
fn point(line: &MyPoint, p: &MyPoint) -> MyPoint {
*line + *p
}
}
//--------------------------------------
//------ definition of abstract method by trait bound ------
trait PointPolymorphism {
fn point_poly<PM: PointMethod>(&self, p: &MyPoint) -> MyPoint;
}
impl PointPolymorphism for MyPoint {
fn point_poly<PM: PointMethod>(&self, p: &MyPoint) -> MyPoint {
PM::point(self, p)
}
}
//----------------------------------------------------------
impl std::ops::Add<MyPoint> for MyPoint {
type Output = MyPoint;
fn add(self, rhs: MyPoint) -> Self::Output {
MyPoint(self.0+rhs.0, self.1+rhs.1)
}
}
簡単な解説
-
MyPoint
が持つ座標を変更するメソッドをpoint_poly
として多相定義-
Absolute
で指定座標に変更、Relative
で座標を移動させる
-
- それぞれの型
Absolute
とRelative
をenumとして定義 - トレイト
PointMethod
とその実装で呼び出された際の振る舞いを各型向けに定義 - トレイト
PointPolymorphism
内でのPointMethod
のメソッド呼び出しを自作構造体向けに定義 - 自作構造体から
PointPolymorphism
のメソッドを型指定して呼び出す- 理解優先で
point_poly
としたがpoint
とするとよりスマートに見える
- 理解優先で
Discussion