为什么newtypes不使用内部类型的特征?

Ror*_*ory 7 rust newtype

生锈1.0.0每晚,这个代码工作正常:

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

但是如果我尝试使用newtype(根据锈书):

struct Metres(f64);

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

我得到这个编译器错误:

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
Run Code Online (Sandbox Code Playgroud)

既然Metres基本上是一个f64,为什么编译器不能使用相同的+运算符,并为其创建一个新Metres对象z

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

(关于这个问题有一个老问题,但生锈变化很多,因此我正在重新研究)

Sco*_*son 10

newtypes以这种方式工作的原因通常是因为你避免在底层类型上定义的特征.例如,你可以拥有MetresFeet哪些都包装,f64但定义添加MetresFeet进行单位转换,这是普通的f64添加不能给你.

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


Mat*_* M. 5

正如斯科特·奥尔森(Scott Olson)所提到的,新类型在其唯一属性中不会"退化"实际上是自愿的.毕竟,他们在这里介绍一种新型.

如果您想要的只是一个同义词,但稍有不同,那么您可以使用类型别名:

type Metres = f64;
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)