Struct 自动为新类型(具有一个字段的元组结构)实现封闭类型的特征

Struct 自动为新类型(具有一个字段的元组结构)实现封闭类型的特征,struct,traits,rust,newtype,Struct,Traits,Rust,Newtype,在Rust中,只能创建一个字段的元组结构,如下所示: struct Centimeters(i32); 我想用厘米进行基本运算,而不必每次通过模式匹配提取其“内部”值,也不必实现添加,子。。。特性和重载运算符 我想做的是: let a = Centimeters(100); let b = Centimeters(200); assert_eq!(a + a, b); 有没有一种方法可以做到这一点,而不必每次通过模式匹配提取它们的“内部”值,也不必实现Add、Sub。。。特征和重载操作符 不

在Rust中,只能创建一个字段的元组结构,如下所示:

struct Centimeters(i32);
我想用
厘米
进行基本运算,而不必每次通过模式匹配提取其“内部”值,也不必实现
添加
。。。特性和重载运算符

我想做的是:

let a = Centimeters(100);
let b = Centimeters(200);
assert_eq!(a + a, b);
有没有一种方法可以做到这一点,而不必每次通过模式匹配提取它们的“内部”值,也不必实现Add、Sub。。。特征和重载操作符

不,唯一的方法是手动实现这些特性。Rust没有一个等价物,它允许对包装类型进行
派生
,以自动实现包装类型所实现的任何类型类/特征(并且当前将Rust的
#[派生]
设置为一个简单的AST转换,像Haskell一样实现它基本上是不可能的。)

要简化此过程,可以使用宏:

use std::ops::{Add, Sub};

macro_rules! obvious_impl {
    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
        impl $trait_<$type_> for $type_ {
            type Output = $type_;

            fn $method(self, $type_(b): $type_) -> $type_ {
                let $type_(a) = self;
                $type_(a.$method(&b))
            }
        }
    }
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Centimeters(i32);

obvious_impl! { impl Add for Centimeters { fn add } }
obvious_impl! { impl Sub for Centimeters { fn sub } }

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Inches(i32);

obvious_impl! { impl Add for Inches { fn add } }
obvious_impl! { impl Sub for Inches { fn sub } }

fn main() {
    let a = Centimeters(100);
    let b = Centimeters(200);
    let c = Inches(10);
    let d = Inches(20);
    println!("{:?} {:?}", a + b, c + d); // Centimeters(300) Inches(30)
    // error:
    // a + c;
}
这允许您编写
self.amt
,而无需进行模式匹配。您还可以定义一个函数,如
fn cm(x:i32)->cm{cm{amt:x}}
,称为like
cm(100)
,以避免构建完整结构的繁琐

您还可以使用
.0
.1
语法访问元组结构的内部值

有没有一种方法可以做到这一点,而不必每次通过模式匹配提取它们的“内部”值,也不必实现Add、Sub。。。特征和重载操作符

不,唯一的方法是手动实现这些特性。Rust没有一个等价物,它允许对包装类型进行
派生
,以自动实现包装类型所实现的任何类型类/特征(并且当前将Rust的
#[派生]
设置为一个简单的AST转换,像Haskell一样实现它基本上是不可能的。)

要简化此过程,可以使用宏:

use std::ops::{Add, Sub};

macro_rules! obvious_impl {
    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
        impl $trait_<$type_> for $type_ {
            type Output = $type_;

            fn $method(self, $type_(b): $type_) -> $type_ {
                let $type_(a) = self;
                $type_(a.$method(&b))
            }
        }
    }
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Centimeters(i32);

obvious_impl! { impl Add for Centimeters { fn add } }
obvious_impl! { impl Sub for Centimeters { fn sub } }

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Inches(i32);

obvious_impl! { impl Add for Inches { fn add } }
obvious_impl! { impl Sub for Inches { fn sub } }

fn main() {
    let a = Centimeters(100);
    let b = Centimeters(200);
    let c = Inches(10);
    let d = Inches(20);
    println!("{:?} {:?}", a + b, c + d); // Centimeters(300) Inches(30)
    // error:
    // a + c;
}
这允许您编写
self.amt
,而无需进行模式匹配。您还可以定义一个函数,如
fn cm(x:i32)->cm{cm{amt:x}}
,称为like
cm(100)
,以避免构建完整结构的繁琐


您还可以使用
.0
.1
语法访问元组结构的内部值。

对于Rust版本1.10.0,在我看来,类型别名完全适合您描述的情况。他们只是给一个类型一个不同的名称

假设所有厘米都是u32。然后我就可以使用代码了

type Centimeters = u32;

任何
u32
具有的特征,
厘米将自动具有。这并不能排除将
厘米
添加到
英寸
的可能性。如果您很小心,就不需要使用不同的类型。

对于Rust 1.10.0版,在我看来,类型别名完全适合您描述的情况。他们只是给一个类型一个不同的名称

假设所有厘米都是u32。然后我就可以使用代码了

type Centimeters = u32;
任何
u32
具有的特征,
厘米将自动具有。这并不能排除将
厘米
添加到
英寸
的可能性。如果你小心的话,你就不需要不同的类型了。

我为这个问题做了准备。它可以为元素实现它们的结构派生许多特性

您需要向您的
Cargo.toml
添加
derivate\u more
。然后你可以写:

#[macro_use]
extern crate derive_more;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Add)]
struct Centimeters(i32);

fn main() {
    let a = Centimeters(100);
    let b = Centimeters(200);
    assert_eq!(a + a, b);
}
我对这个问题提出了解决方案。它可以为元素实现它们的结构派生许多特性

您需要向您的
Cargo.toml
添加
derivate\u more
。然后你可以写:

#[macro_use]
extern crate derive_more;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Add)]
struct Centimeters(i32);

fn main() {
    let a = Centimeters(100);
    let b = Centimeters(200);
    assert_eq!(a + a, b);
}

我几乎可以肯定宏是正确的选择,但我还没有掌握它们:)如果你建议使用合适的结构,那么单字段结构的具体用例是什么?@anonymous\u user\u 13你是说单字段元组结构?默认的构造语法更好,我能想到的唯一好处就是不必为字段指定名称。我几乎可以肯定宏是最好的选择,但是我还没有掌握它们:)如果你建议使用合适的结构,那么单字段结构的具体用例是什么?@anonymous\u user\u 13你是说单字段元组结构?默认的构造语法更好,我能想到的唯一好处就是不必为字段指定名称。如果你小心,就不需要不同的类型。-如果你足够小心,你就不需要像Rust一样的语言。类型应该对程序员有所帮助。同意只提供一个潜在的ideaD通过引入类型别名(如上所述)和新类型(类似,但没有隐式转换)进一步实现了这一点。如果你小心的话,你就不需要不同的类型了。-如果你足够小心,你就不需要像Rust一样的语言。类型应该对程序员有所帮助。同意仅仅提供一个潜在的ideaD通过引入类型别名(如上所述)和新类型(类似,但没有隐式转换)进一步实现了这一点。