Generics 基于特征的通用实现

Generics 基于特征的通用实现,generics,rust,traits,Generics,Rust,Traits,定义泛型结构时,Rust中是否有方法根据给定泛型类型T实现的特征使用不同的方法实现 例如: struct S<T> { value: T, } impl<T> S<T> { fn print_me(&self) { println!("I cannot be printed"); } } impl<T: std::fmt::Display> S<T> { f

定义泛型
结构时,Rust中是否有方法根据给定泛型类型
T
实现的特征使用不同的方法实现

例如:

struct S<T> {
    value: T,
}

impl<T> S<T> {
    fn print_me(&self) {
        println!("I cannot be printed");
    }
}

impl<T: std::fmt::Display> S<T> {
    fn print_me(&self) {
        println!("{}", self.value);
    }
}

fn main() {
    let s = S { value: 2 };
    s.print_me();
}
结构{
值:T,
}
impl S{
fn打印(自我和自我){
println!(“我无法打印”);
}
}
impl S{
fn打印(自我和自我){
println!(“{}”,self.value);
}
}
fn main(){
设s=s{value:2};
s、 打印我();
}

有一个称为的不稳定功能,它允许多个
impl
只要其中一个块比另一个块更具体,则应用于同一类型的块:

#![专题(专门化)]
结构打印机(T);
特征印花{
fn打印(和自我);
}
//专门实施
打印机的impl打印{
fn打印(&self){
println!(“{}”,self.0);
}
}
//默认实现
打印机的impl打印{
默认fn打印(&self){
println!(“我无法打印”);
}
}
结构不显示;
fn main(){
let not_printable=打印机(NotDisplay);
让printable=Printer(“Hello World”);
不可打印。打印();
printable.print();
}
//=>我无法打印
//=>你好,世界
对于稳定锈病,我们需要一些其他机制来实现专门化。Rust还有另一种语言功能可以做到这一点:。编译器的规则是,如果一个方法可以在没有autoref的情况下被调度,那么它将被调度。只有在没有autoref的情况下无法调度方法时,编译器才会插入autoref并再次尝试解析它。所以在这个例子中:

impl打印值{
fn打印(自我){
println!(“按价值调用”);
}
}
值的impl打印(&V){
fn打印(自我){
println!(“在价值上被调用”);
}
}
Value
的实现将优先于
和Value
。了解这一规则,我们可以模拟稳定锈的特殊化:

struct打印机(T);
特征印花{
fn打印(和自我);
}
//专门实施
打印机的impl打印{
fn打印(&self){
println!(“{}”,self.0);
}
}
特征默认打印{
fn打印(和自我);
}
//默认实现
//
//请注意,此impl的Self类型是&Printer,因此
//方法参数实际上是&&T!
//这使得该impl在方法期间的优先级较低
//分辨率高于上述“打印”的实现。
打印机的默认打印(&R){
fn打印(&self){
println!(“我无法打印”);
}
}
结构不显示;
fn main(){
let not_printable=打印机(NotDisplay);
让printable=Printer(“Hello World”);
(&U不可打印)。打印();
(&printable).print();
}
//=>我无法打印
//=>你好,世界
编译器将首先尝试使用
打印
实现。如果不能(因为类型不是
Display
),它将使用更通用的
DefaultPrint
实现

该技术应用方法解析的方式不能用特征边界来描述,因此它不适用于常规方法,因为我们必须在特征之一(
DefaultPrint
Print
)之间进行选择:

fn打印(值:T){
(&value).print()
}
但是,此技巧对于宏非常有用,因为宏不需要指定特征边界:

macro\u规则!印刷品{
($e:expr)=>{
(&$e).print()
};
}
打印!(不可打印);//=>我无法打印
打印!(可打印);//=>你好,世界

不幸的是,没有。专业化一旦登陆,但它可能会。另外,你可能是指
s.print\u me()
而不是
s.do\u it()
@user4815162342你是对的,编辑如果你可以制作
print\u me
一个宏,这在今天的稳定锈上是可能的:添加一些东西:这实际上不需要宏来工作,这只是糖。它对函数的泛型不起作用:如果定义fn run(something:t){let checker=S{value:something};print_me!(checker);}然后运行(“hello”);仍然会导致“我无法打印”。@DanielV如果有好的观点,我会更新答案。