[英]How can I use the same default implementation for this Rust trait
I want to implement a trait that allows assigning generic types.我想实现一个允许分配泛型类型的特征。 So far I have tested this for
u32
and String
types:到目前为止,我已经对
u32
和String
类型进行了测试:
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);
}
I know this code is not perfect, and I should be using a Result
return instead of unwrapping, but please set this aside as this is a quick example.我知道这段代码并不完美,我应该使用
Result
返回而不是展开,但请把它放在一边,因为这是一个简单的例子。 The implementations for u32
and String
are exactly the same, so I would like to use a default implementation for both instead of copying & pasting the code. u32
和String
的实现完全相同,所以我想对两者都使用默认实现,而不是复制和粘贴代码。 I have tried using one, but as the returned type Self
differs in both, compiler cannot determine the type size and errors.我试过使用一个,但由于返回的类型
Self
在两者中都不同,编译器无法确定类型大小和错误。
How could I write a default implementation in this case?在这种情况下,我该如何编写默认实现?
The following bounds on Self
are required for the default implementation:默认实现需要以下
Self
边界:
Self: Sized
because Self
is returned from the function and will be placed in the caller's stack Self: Sized
,因为Self
是从 function 返回的,将被放入调用者的堆栈中Self: FromStr
because you're calling parse()
on input
and expecting it to produce a value of type Self
Self: FromStr
因为您在input
上调用parse()
并期望它产生一个Self
类型的值<Self as FromStr>::Err: Debug
because when you unwrap
a potential error and the program panics Rust wants to be able to print the error message, which requires the error type to implement Debug
<Self as FromStr>::Err: Debug
因为当你unwrap
一个潜在的错误并且程序崩溃时 Rust 希望能够打印错误消息,这需要错误类型来实现Debug
Full implementation:全面实施:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self
where
Self: Sized + FromStr,
<Self as FromStr>::Err: Debug,
{
input.parse().unwrap()
}
}
impl Test for String {}
impl Test for u32 {}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
A generic blanket implementation is also possible, where you automatically provide an implementation of Test
for all types which satisfy the trait bounds:通用的一揽子实现也是可能的,您可以在其中自动为满足特征界限的所有类型提供
Test
的实现:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self;
}
impl<T> Test for T
where
T: Sized + FromStr,
<T as FromStr>::Err: Debug,
{
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);
}
This implementation, similar to the default implementation, allows you to pick which types get the implementation, but it's also similar to the generic implementation, in that it doesn't require you to modify the trait method signature with any additional trait bounds:这个实现,类似于默认实现,允许你选择哪些类型得到实现,但它也类似于通用实现,因为它不需要你用任何额外的 trait 边界修改 trait 方法签名:
trait Test {
fn test(&self, input: &str) -> Self;
}
macro_rules! impl_Test_for {
($t:ty) => {
impl Test for $t {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
}
}
impl_Test_for!(u32);
impl_Test_for!(String);
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
The key differences between the 3 approaches:三种方法之间的主要区别:
Test
must be sized, and have a FromStr
impl with a debuggable error type.Test
的类型都必须调整大小,并具有带有可调试错误类型的FromStr
impl。Test
implementations.Test
实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.