繁体   English   中英

如何使用特征默认方法中的BorrowMut超特征访问结构域?

[英]How do I use a BorrowMut supertrait to access struct fields in a trait default method?

考虑以下Rust代码

trait Trait {
    fn show_name(&self) {}
}

struct Foo {
    name: String,
    things_and_stuff: usize,
}

impl Trait for Foo {
    fn show_name(&self) {
        println!("{}", self.name);
    }
}

struct Bar {
    name: String,
    other_field: i32,
}

impl Trait for Bar {
    fn show_name(&self) {
        println!("{}", self.name);
    }
}

这两个show_name函数具有完全相同的代码。 如果可以将该方法作为Trait的默认方法,那将很方便,但这是不可能的,因为traits无法访问struct字段。

我们可以在Trait上声明一个get_name(&self) -> &str方法,并在FooBar上实现它,但这不能解决重复代码的问题,因为get_name两种实现都是相同的。

最好避免代码重复。 另一个问题已经问到是否可以在性状中进行田间访问,而答案基本上是“否”。 但是,我在rust-internals论坛上发现了一条评论 ,暗示已经有可能。 这是代码:

struct Fields {
    name: String,
}

trait Trait: BorrowMut<Fields> {
    // methods go here
}

impl<T> Trait for T where T: BorrowMut<Fields> {}

大概有一种方法可以使T类型成为BorrowMut<Fields>并使用它来允许Trait访问Fields的字段,但是到目前为止,我不确定这将如何工作。

上面显示的代码片段应如何解决在特征中获取字段访问的问题?


我知道有人在讨论将特质中的字段访问添加到该语言( rust-internalsRFC另一个RFC )中,但是我想知道现在有什么可能。

答案基本上是“否”

答案实际上是(强调我的):

默认实现只能使用在特征或超级特征中定义的方法。

这就是您的代码段所做的:

trait Trait: BorrowMut<Fields>

要使其正常工作,请遵循您所引用的帖子中的建议:

选择实现BorrowMut<Foo>所有类型

因此,您需要为每种类型实现特征。 我切换到Borrow是因为这里不需要可变性:

use std::borrow::Borrow;

struct Fields {
    name: String,
}

trait Trait: Borrow<Fields> {
    fn show_name(&self) {
        let fields: &Fields = self.borrow();
        println!("{}", fields.name);
    }
}

struct Foo {
    fields: Fields,
    things_and_stuff: usize,
}

impl Borrow<Fields> for Foo {
    fn borrow(&self) -> &Fields {
        &self.fields
    }
}

struct Bar {
    fields: Fields,
    other_field: i32,
}

impl Borrow<Fields> for Bar {
    fn borrow(&self) -> &Fields {
        &self.fields
    }
}

impl<T> Trait for T where T: Borrow<Fields> {}

我几乎可以肯定您不会喜欢这种解决方案,因为它

不能解决重复代码的问题,因为两个实现都相同

如果您的目标是减少代码中重复字符的数量,则可能更喜欢编写宏。

也可以看看:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM