Function trait_object_to_enum

Source
pub fn trait_object_to_enum()
Expand description

§当不能实现 trait 对象当时候该如何?

  1. 将其转化为 Enum

trait 对象代码:

    trait KnobControl {
        fn set_position(&mut self, value: f64);
        fn get_value(&self) -> f64;
    }

    struct LinearKnob {
        position: f64,
    }

    struct LogarithmicKnob {
        position: f64,
    }

    impl KnobControl for LinearKnob {
        fn set_position(&mut self, value: f64) {
            self.position = value;
        }

        fn get_value(&self) -> f64 {
            self.position
        }
    }

    impl KnobControl for LogarithmicKnob {
        fn set_position(&mut self, value: f64) {
            self.position = value;
        }

        fn get_value(&self) -> f64 {
            (self.position + 1.).log2()
        }
    }

    fn main() {
        let v: Vec<Box<dyn KnobControl>> = vec![
            //set the knobs
        ];

        //use the knobs
    }

转为 enum:

    enum Knob {
        Linear(LinearKnob),
        Logarithmic(LogarithmicKnob),
    }

    impl KnobControl for Knob {
        fn set_position(&mut self, value: f64) {
            match self {
                Knob::Linear(inner_knob) => inner_knob.set_position(value),
                Knob::Logarithmic(inner_knob) => inner_knob.set_position(value),
            }
        }

        fn get_value(&self) -> f64 {
            match self {
                Knob::Linear(inner_knob) => inner_knob.get_value(),
                Knob::Logarithmic(inner_knob) => inner_knob.get_value(),
            }
        }
    }

当 trait 不满足对象安全规则的时候,也可以用 Enum 代替。

#![allow(unused)]

use core::ops::Add;

trait KnobControl<T: Add + Add<Output = T> + Copy> {
    fn set_position(&mut self, value: T);
    fn get_value(&self, p: T) -> T;
}

struct LinearKnob<T: Add+ Add<Output = T> + Copy> {
    position: T,
}

struct LogarithmicKnob<T: Add+ Add<Output = T> + Copy>  {
    position: T,
}

impl<T: Add+ Add<Output = T> + Copy> KnobControl<T> for LinearKnob<T> {
    fn set_position(&mut self, value: T) {
        self.position = value;
    }

    fn get_value(&self, p: T) -> T {
        self.position + p
    }
}

impl<T: Add+ Add<Output = T> + Copy> KnobControl<T> for LogarithmicKnob<T> {
    fn set_position(&mut self, value: T) {
        self.position = value;
    }

    fn get_value(&self, p: T) -> T {
        (self.position + p)
    }
}

fn main() {
    enum Knob<T: Add+ Add<Output = T> + Copy> {
        Linear(LinearKnob<T>),
        Logarithmic(LogarithmicKnob<T>),
    }

    impl<T: Add+ Add<Output = T> + Copy> KnobControl<T> for Knob<T> {
        fn set_position(&mut self, value: T) {
            match self {
                Knob::Linear(inner_knob) => inner_knob.set_position(value),
                Knob::Logarithmic(inner_knob) => inner_knob.set_position(value),
            }
        }

        fn get_value(&self, p: T) -> T {
            match self {
                Knob::Linear(inner_knob) => inner_knob.get_value(p),
                Knob::Logarithmic(inner_knob) => inner_knob.get_value(p),
            }
        }
    }
}

  1. 利用 “魔法” ,相当于加一层代理 : 参考:https://github.com/dtolnay/erased-serde/blob/master/explanation/main.rs