Метод объекта-черты, который принимает несколько типов чисел c - PullRequest
0 голосов
/ 01 мая 2020

Мне нужен метод объекта-черты, который принимает несколько типов чисел c, каждый из которых будет преобразован в f64. Следующее не компилируется, поскольку NumCast реализует черту Sized:

use num_traits::NumCast;

pub trait Grapher {
    fn add(&mut self, key: &str, number: &dyn NumCast);
    fn show(&self);
}

Обобщенная c версия такого метода отключает Grapher для создания объекта:

fn agregar<T: NumCast>(&mut self, key: &str, number: &T);

Мое решение состояло в том, чтобы создать другую черту:

pub trait F64Convertible {
    fn convert(&self) -> f64;
}

impl F64Convertible for i32 {
    fn convert(&self) -> f64 {
        *self as f64
    }
}

impl F64Convertible for u8 {
    fn convert(&self) -> f64 {
        *self as f64
    }
}
// same for many numeric types...

// use the trait:
pub trait Grapher {
    fn add(&mut self, key: &str, number: &dyn F64Convertible);
    fn show(&self);
}

Я хотел бы избежать повторяющихся функций преобразования в моем коде, возможно, используя NumCast или подобную черту.

1 Ответ

1 голос
/ 01 мая 2020

Я думаю, что в данном конкретном случае было бы не очень полезно принимать dyn NumCast, потому что NumCast имеет только fn from(self), который создает новое число из другого (тогда как вы, вероятно, хотите указать число) .

Теперь, в этом примере, вы можете сойти с рук просто потребовать ToPrimitive:

fn add(&mut self, key: &str, number: &dyn ToPrimitive) {
    number.to_f64();
}

Но перед тем, как воспользоваться этим решением, я спрашиваю себя, не будет ли оно проще, если ваша функция просто приняла Option<f64> (или даже f64). Таким образом, ясно, что ваша функция на самом деле работает на f64, и вызывающие просто должны знать об этом. Более того, простое принятие типа, фактически требуемого функцией, требует некоторых приведений на месте вызова, но обычно приводит к меньшему количеству приведений во время выполнения.

...