👌
自作構造体にアドホック多相を実装する(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