Methods 我如何使用相同的默认实现来实现这个问题

Methods 我如何使用相同的默认实现来实现这个问题,methods,rust,default,traits,Methods,Rust,Default,Traits,我想实现一个允许分配泛型类型的特性。到目前为止,我已经对u32和字符串类型进行了测试: 我知道这段代码并不完美,我应该使用结果返回而不是展开,但请把它放在一边,因为这是一个快速示例。u32和String的实现是完全相同的,因此我想使用默认实现来代替复制和粘贴代码。我尝试过使用一个,但由于返回的类型本身在这两个方面都不同,编译器无法确定类型大小和错误 在这种情况下,如何编写默认实现?默认实现 默认实现需要以下Self边界: Self:Sized,因为Self是从函数返回的,并且将放在调用方的堆栈中

我想实现一个允许分配泛型类型的特性。到目前为止,我已经对u32和字符串类型进行了测试:

我知道这段代码并不完美,我应该使用结果返回而不是展开,但请把它放在一边,因为这是一个快速示例。u32和String的实现是完全相同的,因此我想使用默认实现来代替复制和粘贴代码。我尝试过使用一个,但由于返回的类型本身在这两个方面都不同,编译器无法确定类型大小和错误

在这种情况下,如何编写默认实现?

默认实现 默认实现需要以下Self边界:

Self:Sized,因为Self是从函数返回的,并且将放在调用方的堆栈中 Self:FromStr,因为您正在对输入调用parse,并希望它生成Self类型的值 ::Err:Debug,因为当您打开一个潜在错误并且程序崩溃时,Rust希望能够打印错误消息,这需要错误类型来实现Debug 全面实施:

使用std::fmt::Debug; 使用std::str::FromStr; 性状测试{ fn测试和自我,输入:&str->自我 哪里 Self:size+FromStr, ::错误:调试, { input.parse.unwrap } } 字符串{}的impl测试 u32{}的impl测试 fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 通用实现 也可以使用通用的总体实现,其中您可以自动为满足特征边界的所有类型提供测试实现:

使用std::fmt::Debug; 使用std::str::FromStr; 性状测试{ fn测试和自我,输入:&str->self; } T的impl测试 哪里 T:Size+FromStr, ::错误:调试, { fn测试和自我,输入:&str->自我{ input.parse.unwrap } } fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 宏实现 此实现类似于默认实现,允许您选择获得实现的类型,但它也类似于泛型实现,因为它不要求您使用任何附加的trait边界修改trait方法签名:

性状测试{ fn测试和自我,输入:&str->self; } 宏规则!应用测试{ $t:ty=>{ $t的impl测试{ fn测试和自我,输入:&str->自我{ input.parse.unwrap } } } } 执行测试!u32; 执行测试!一串 fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 关键区别 这三种方法之间的主要区别是:

默认实现使trait边界成为方法签名的固有特性,因此impl测试的所有类型都必须调整大小,并且具有带有可调试错误类型的FromStr impl。 默认实现允许您有选择地选择哪些类型获得测试实现。 泛型实现不会向trait方法的签名添加任何trait边界,因此更多种类的类型可能实现该trait。 对于满足边界的所有类型,泛型实现都会自动实现trait,如果您不希望实现某些类型的trait,则不能有选择地选择退出泛型实现。 宏实现不需要使用附加的trait边界修改trait方法签名,并允许您有选择地选择哪些类型获得实现。 宏实现是一个宏,它具有宏的所有缺点:更难读、写、维护、增加编译时间,并且宏对于静态代码分析器来说本质上是不透明的,这使得很难轻松地对代码进行类型检查。 默认实现 默认实现需要以下Self边界:

Self:Sized,因为Self是从函数返回的,并且将放在调用方的堆栈中 Self:FromStr,因为您正在对输入调用parse,并希望它生成Self类型的值 ::Err:Debug,因为当您打开一个潜在错误并且程序崩溃时,Rust希望能够打印错误消息,这需要错误类型来实现Debug 全面实施:

使用std::fmt::Debug; 使用std::str::FromStr; 性状测试{ fn测试和自我,输入:&str->自我 哪里 Self:size+FromStr, ::错误:调试, { input.parse.unwrap } } 字符串{}的impl测试 u32{}的impl测试 fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 通用实现 泛型 也可以使用一揽子实现,自动为满足特征边界的所有类型提供测试实现:

使用std::fmt::Debug; 使用std::str::FromStr; 性状测试{ fn测试和自我,输入:&str->self; } T的impl测试 哪里 T:Size+FromStr, ::错误:调试, { fn测试和自我,输入:&str->自我{ input.parse.unwrap } } fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 宏实现 此实现类似于默认实现,允许您选择获得实现的类型,但它也类似于泛型实现,因为它不要求您使用任何附加的trait边界修改trait方法签名:

性状测试{ fn测试和自我,输入:&str->self; } 宏规则!应用测试{ $t:ty=>{ $t的impl测试{ fn测试和自我,输入:&str->自我{ input.parse.unwrap } } } } 执行测试!u32; 执行测试!一串 fn干线{ 设mut var=0u32; 让mut st=String::default; var=var.test12345678; st=st.testText; println!{},{},var,st; } 关键区别 这三种方法之间的主要区别是:

默认实现使trait边界成为方法签名的固有特性,因此impl测试的所有类型都必须调整大小,并且具有带有可调试错误类型的FromStr impl。 默认实现允许您有选择地选择哪些类型获得测试实现。 泛型实现不会向trait方法的签名添加任何trait边界,因此更多种类的类型可能实现该trait。 对于满足边界的所有类型,泛型实现都会自动实现trait,如果您不希望实现某些类型的trait,则不能有选择地选择退出泛型实现。 宏实现不需要使用附加的trait边界修改trait方法签名,并允许您有选择地选择哪些类型获得实现。 宏实现是一个宏,它具有宏的所有缺点:更难读、写、维护、增加编译时间,并且宏对于静态代码分析器来说本质上是不透明的,这使得很难轻松地对代码进行类型检查。
这些边界是否仅适用于默认实现或函数的一般用法?提供一个具有这些边界的总括实现会更好吗?也就是说,我希望它能工作,OP可能也能,但它不能:@SebastianRedl。我还更新了我的答案,加入了这个替代方法。@pretzelhammer:非常感谢你完整而详细的回答。我还不知道宏是如何工作的,但最终会实现的。我喜欢你也给出了一个通用的实现。谢谢这些边界是否仅适用于默认实现或函数的一般用法?提供一个具有这些边界的总括实现会更好吗?也就是说,我希望它能工作,OP可能也能,但它不能:@SebastianRedl。我还更新了我的答案,加入了这个替代方法。@pretzelhammer:非常感谢你完整而详细的回答。我还不知道宏是如何工作的,但最终会实现的。我喜欢你也给出了一个通用的实现。谢谢
trait Test {
    fn test(&self, input: &str) -> Self;
}

impl Test for String {
    fn test(&self, input: &str) -> Self {
        input.parse().unwrap()
    }
}

impl Test for u32 {
    fn test(&self, input: &str) -> Self {
        input.parse().unwrap()
    }
}

fn main() {
    let mut var = 0u32;
    let mut st = String::default();

    var = var.test("12345678");
    st = st.test("Text");
    println!("{}, {}", var, st);
}