生锈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以这种方式工作的原因通常是因为你想避免在底层类型上定义的特征.例如,你可以拥有Metres
和Feet
哪些都包装,f64
但定义添加Metres
和Feet
进行单位转换,这是普通的f64
添加不能给你.
当然,有时您确实需要基础特征实施.目前,您必须自己编写一个包装器实现,但是有一个RFC可以自动生成这些实现:https://github.com/rust-lang/rfcs/issues/479
正如斯科特·奥尔森(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)