Должен ли я использовать enum для эмуляции полиморфизма или использовать вместо него черту с Box <trait>? - PullRequest
0 голосов
/ 09 сентября 2018

Использование enum Axes для ограничения Coordinate и Quaternion:

#[derive(Clone)]
pub enum Axes {
    Coordinate {x: f64, y: f64, z: f64, reserve: Vec<f64>,},
    Quaternion {x: f64, y: f64, z: f64},
}

impl Axes {
    pub fn shift(&mut self, Sample: &Axes) -> () {
        let Dup: Axes = self.clone();
        match Dup {
            Axes::Coordinate {x, y, z, reserve} => {
                match &Sample {
                    Axes::Coordinate {x, y, z, reserve} => {
                        *self = Axes::Coordinate {x: *x, y: *y, z: *z, reserve: reserve.to_vec()};
                    }
                    _ => panic!(),
                }
            }
            Axes::Quaternion {x, y, z} => {
                match &Sample {
                    Axes::Quaternion {x, y, z} => {
                        *self = Axes::Quaternion {x: *x, y: *y, z: *z};
                    }
                    _ => panic!(),
                }
            }
        }
    }
}

Использование черты Axes для связи struct Coordinate и Quaternion:

pub trait Axes {
    fn shift(&mut self, Sample: &Axes) -> ();
    fn fold(&mut self, Sample: &Axes) -> ();
}

pub struct Coordinate {
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub reserve: Vec<f64>,
}

pub struct Quaternion {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Axes for Coordinate {
    fn shift(&mut self, Sample: &Axes) -> () { }
    fn fold(&mut self, Sample: &Axes) -> () { }
}

impl Axes for Quaternion {
    fn shift(&mut self, Sample: &Axes) -> () { }
    fn fold(&mut self, Sample: &Axes) -> () { }
}

Является ли черта с struct в этом случае более доступной и более эффективной? Я в некотором роде смущен тем, что использовать в каких случаях.

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Другое отличие, не упомянутое в ответе @ Kwarrtz, связано с памятью.

  • enum s может храниться непосредственно в стеке, в то время как для штучной черты всегда требуется куча. То есть enum s дешевы в создании, а штучные черты - нет.
  • экземпляр enum всегда будет таким же большим, как его самый большой вариант (плюс дискриминант в большинстве случаев), даже если вы храните в основном небольшие варианты. Это было бы проблемой в случае, подобном этому:

    enum Foo {
        SmallVariant(bool),
        BigVariant([u64; 100]),
    }
    

    Если бы вы хранили N экземпляров этого типа в векторе, вектору всегда требовалось бы N*(100*sizeof::<u64> + sizeOfDiscriminant) байтов памяти, даже если вектор содержит только SmallVariant с.

    Если бы вы использовали черту в штучной упаковке, вектор использовал бы N * sizeOfFatPointer == N * 2 * sizeof::<usize>.

0 голосов
/ 09 сентября 2018

Одно из больших различий между использованием черт и перечислений в вашей ситуации - это их расширяемость.Если вы сделаете Axes перечислением, то эти два параметра будут жестко закодированы в тип.Если вы хотите добавить какую-то третью форму оси, вам придется изменить сам тип, что, вероятно, потребует большого количества модификаций кода с использованием Axes (например, где бы вы ни подходили для Axes, возможно, потребуетсябыть измененным).С другой стороны, если вы сделаете Axes признаком, вы можете добавить другие типы осей, просто определив новый тип и написав соответствующую реализацию, вообще не изменяя существующий код.Это может быть сделано даже за пределами библиотеки, например, пользователем.

Другая важная вещь, которую следует учитывать, - это какой доступ вам необходим к внутренним структурам структур.С помощью перечисления вы получаете полный доступ ко всем данным, хранящимся в структуре.Если вы хотите написать функцию, которая может работать как с Coordinate, так и с Quaternion, используя черту, то вы сможете выполнять только те операции, которые описаны в черте Axes (в данном случае Shift иFold).Например, учитывая реализацию Axes, которую вы дали, у вас не будет возможности просто получить кортеж (X,Y,Z) через интерфейс Axes.Если вам нужно сделать это в какой-то момент, вам придется добавить новый метод.

Не зная больше о том, как вы планируете использовать эти типы, трудно сказать наверняка, какой из этих вариантов является лучшим выбором., но если бы это был я, я бы использовал перечисление.В конечном счете, все сводится к предпочтениям, но, надеюсь, это даст вам представление о том, о чем нужно думать при принятии решения.

...