首页 > 解决方案 > 如何根据泛型类型是否实现特征以不同方式实现函数?

问题描述

我想do_something根据泛型类型是否实现来实现有条件TDebug。有没有办法做这样的事情?

struct A(i32);

#[derive(Debug)]
struct B(i32);

struct Foo<T> {
    data: T,
    /* more fields */
}

impl<T> Foo<T> {
    fn do_something(&self) {
        /* ... */
        println!("Success!");
    }

    fn do_something(&self)
    where
        T: Debug,
    {
        /* ... */
        println!("Success on {:?}", self.data);
    }
}

fn main() {
    let foo = Foo {
        data: A(3), /* ... */
    };
    foo.do_something(); // should call first implementation, because A
                        // doesn't implement Debug

    let foo = Foo {
        data: B(2), /* ... */
    };
    foo.do_something(); // should call second implementation, because B
                        // does implement Debug
}

我认为做到这一点的一种方法是创建一个我们必须定义的特征do_something(&Self),但我不确定。我的代码片段是我将首先尝试的。

标签: rustgeneric-programming

解决方案


这是基于夜间功能专业化的解决方案:

#![feature(specialization)]

use std::fmt::Debug;

struct A(i32);

#[derive(Debug)]
struct B(i32);

struct Foo<T> {
    data: T,
    /* more fields */
}

trait Do {
    fn do_something(&self);
}

impl<T> Do for Foo<T> {
    default fn do_something(&self) {
        /* ... */
        println!("Success!");
    }
}

impl<T> Do for Foo<T>
where
    T: Debug,
{
    fn do_something(&self) {
        /* ... */
        println!("Success on {:?}", self.data);
    }
}

fn main() {
    let foo = Foo {
        data: A(3), /* ... */
    };
    foo.do_something(); // should call first implementation, because A
                        // doesn't implement Debug

    let foo = Foo {
        data: B(2), /* ... */
    };
    foo.do_something(); // should call second implementation, because B
                        // does implement Debug
}

第一步是创建一个定义do_something(&self). 现在,我们为 定义impl了这个 trait 的两个:一个为所有人实现Foo<T>的通用“父级”和一个仅针对 implements 的子集实现的专用“子级” 。孩子可能会专门研究来自父母的物品。这些我们要专门化的项目需要在 parent 中用关键字进行标记。在您的示例中,我们希望专门化.implTimplTDebugimplimpldefaultimpldo_something


推荐阅读