繁体   English   中英

如何为自我的不同可变性实现特征

[英]How to implement a trait for different mutabilities of self

给定的是一个带有u32字段的结构。 它只有一个重载方法,可以同时用作该字段的 setter 和 getter。

pub struct Struct {
    value: u32
}
pub trait Trait<T> {
    fn method(&mut self, arg: T);
}
impl Trait<u32> for Struct {
    fn method(&mut self, arg: u32) {
        self.value = arg;
    }
}
impl Trait<&mut u32> for Struct {
    fn method(&mut self, arg: &mut u32) {
        *arg = self.value;
    }
}

这种结构的可能用途如下

fn main() {    
    let mut s = Struct { value: 0 };
    let mut v = 0;
    s.method(&mut v);
    println!("The value of s is: {}", v);
    s.method(3);
    s.method(&mut v);
    println!("The value of s is: {}", v);
}

当在 ffi 接口中使用结构时,调用重载方法而不是直接访问字段的优势有两个原因。 一方面,该方法仍然可以对值进行修改,例如先将&str转换为CString ,然后将*const u8存储为值,这使得该字符串可用于 C。另一方面,重载方法还可以使用 C 中为其指定的名称,而不是编写setValuegetValue等。 但是,正如您在此处看到的,这两种方法中的一种不需要对 self 的可变引用,因为它不会更改值字段,但由于特征需要它,所以无论如何都会在两种情况下使用它。 该结构不仅被配置并用作 ffi 方法中的参数,而且还可以作为此类方法的返回值出现,在这种情况下,它将作为不可变引用返回,并且只能从中读取。 定制的特征实现看起来像这样

impl Trait<u32> for Struct {
    fn method(&mut self, arg: u32) {
        self.value = arg;
    }
}
impl Trait<&mut u32> for Struct {
    fn method(&self, arg: &mut u32) {
        *arg = self.value;
    }
}

显然这在这里不起作用,因为第二个 impl 块没有与特征相同的方法签名。 我已经尝试使用arbitrary_self_types功能将 self 参数定义为特征中的另一个通用参数,但不幸的是,这没有用。

您不能参数化可变性。

看:

可以self进行参数化,但它不再是一个方法,只是一个关联的 function:

pub trait Trait<This, T> {
    fn method(this: This, arg: T);
}
impl Trait<&mut Self, u32> for Struct {
    fn method(this: &mut Self, arg: u32) {
        this.value = arg;
    }
}
impl Trait<&Self, &mut u32> for Struct {
    fn method(this: &Self, arg: &mut u32) {
        *arg = this.value;
    }
}

fn main() {
    let mut s = Struct { value: 0 };
    let mut v = 0;
    Struct::method(&s, &mut v);
    println!("The value of s is: {}", v);
    Struct::method(&mut s, 3);
    Struct::method(&s, &mut v);
    println!("The value of s is: {}", v);
}

鉴于 RFC 精炼特性实现草案提出了在其实现中改进特性的可能性,即编写一个不太通用的 impl(例如,特性中不安全的 impl 中的安全方法),您可能能够将来也可以改进可变性(尽管我还没有看到相关讨论),但这只会在您使用具体实例而不是 generics 时放宽限制。

不管怎样,我认为这种设计是不正确的。 只需使用普通的value()set_value()方法,简单明了。

暂无
暂无

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

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