【问题标题】:Why don't newtypes use the traits from the inner type?为什么新类型不使用内部类型的特征?
【发布时间】:2015-01-31 13:18:46
【问题描述】:

在 rust 1.0.0-nightly 中,此代码运行良好:

fn main() {
    let x = 10f64;
    let y = 20f64;
    let z = x + y;
    println!("z = {}", z);
}

但是如果我尝试使用新类型(根据rust book):

struct Metres(f64);

fn main() {
    let x = Metres(10f64);
    let y = Metres(20f64);
    let z = x + y;
    println!("z = {}", z);
}

我得到这个编译器错误:

test.rs:6:13: 6:18 error: binary operation `+` cannot be applied to type `Metres`
test.rs:6     let z = x + y;
                      ^~~~~
error: aborting due to previous error

既然Metres基本上是f64,为什么编译器不能使用同样的+操作符,为z创建一个新的Metres对象?

如果我不能做诸如添加之类的简单事情,我该如何使用新类型?它们如何“非常有用”(正如书中所说)?

(有一个 old question 关于这个,但是 rust 变化很大,所以我再问)

【问题讨论】:

    标签: rust newtype


    【解决方案1】:

    newtypes 以这种方式工作的原因通常是因为您想要避免在底层类型上定义的特征。例如,您可以拥有 MetresFeet ,它们都包装了 f64 但定义了 MetresFeet 的加法来进行单位转换,而普通的 f64 加法不会给你。

    当然,有时您确实需要底层 trait 实现。目前,您必须自己编写包装器实现,但有一个 RFC 可以自动生成这些实现:https://github.com/rust-lang/rfcs/issues/479

    【讨论】:

    • 这实际上很有意义。可惜没有更短的方法来推导事物。
    • 自 2016 年 3 月 28 日起,crate derive_more 将为许多常见特征(如 AddSubMulAssign 等)执行此操作。crates.io/crates/derive_more
    【解决方案2】:

    正如 Scott Olson 所提到的,newtypes 不会在其唯一属性中“退化”实际上是自愿的。毕竟,他们是来介绍一种新类型的。

    如果你想要的只是一个同义词,它略有不同,那么你可以使用类型别名来代替:

    type Metres = f64;
    

    但是,您将失去新类型的好处:

    type Grams = f64;
    
    fn main() {
        let m = 10 as Metres;
        let g = 5 as Grams;
        println!("{}", m + g); // prints 15, see http://is.gd/IdYOEg
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-04
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 2018-12-16
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多