【问题标题】:Trait object's method which accepts several numeric types接受多种数字类型的特征对象的方法
【发布时间】:2020-05-01 02:58:15
【问题描述】:

我想要一个接受多种数字类型的特征对象的方法,所有这些都将转换为f64。以下内容无法编译,因为 NumCast 实现了 Sized 特征:

use num_traits::NumCast;

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

此类方法的通用版本禁用 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 或类似的特征。

【问题讨论】:

  • 在调用函数转换变量时接受一种类型然后使用as有什么问题?
  • 没有错,更多的是理论问题。调用者可能有几种类型的数值。我想接受一系列类型(例如那些实现 NumCast 的类型),避免调用者的转换。

标签: rust traits


【解决方案1】:

我认为在这种特殊情况下,接受dyn NumCast 并没有真正的帮助,因为NumCast 只有一个fn from(self) 可以从另一个数字构造一个新数字(而您可能想提供一个数字) .

现在,在此示例中,您可能只需要 require ToPrimitive

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

但在采用该解决方案之前,我会问自己,如果您的函数仅接受 Option&lt;f64&gt;(甚至是 f64),是否会使事情变得更容易。这样,很明显您的函数实际上在 f64 上工作,调用者只需要注意这一点。此外,简单地接受函数实际需要的类型会在调用站点进行一些类型转换,但通常会导致运行时的类型转换较少。

【讨论】:

  • 它有效,谢谢。在我看来,对于所有/大多数 Sized trait 应该有一个 non-Sized trait(如 toPrimitive),它实现了前 trait 的大部分操作,以允许动态调度。
猜你喜欢
  • 2016-01-25
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 2022-11-16
  • 2016-09-23
  • 2020-08-10
相关资源
最近更新 更多