簡體   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