如何实现不同的自我企业的特征

发布于 2025-01-25 13:40:59 字数 1472 浏览 1 评论 0 原文

给定的是带有 u32 字段的结构。它完全具有一种超载方法,可以用作该字段的设置器和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接口中使用时,有两个原因。一方面,该方法仍然可以对值进行修改,例如首先将&amp; str 转换为 cstring ,然后存储*const u8 作为值,它使得字符串可用于C。另一方面,该方法还可以使用C中使用它的名称,而不是编写 setValue 和<代码> getValue ,例如。但是,正如您在这里看到的那样,这两种方法之一不需要对自我的可变引用,因为它不会改变价值字段,而是因为特征需要它,因此无论如何在两种情况下都使用。该结构不仅在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;
    }
}

明显,因为第二个Inpl Block没有与性状相同的方法签名。我已经尝试使用 notunary_self_types 功能将自我参数定义为性状中的另一个通用参数,但不幸的是这不起作用。

Given is a struct with a u32 field. It has exactly one overloaded method that can be used as both setter and getter for the field.

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;
    }
}

A possible use of this structure could be as follows

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);
}

The advantage of calling an overloaded method instead of accessing the field directly serves two reasons when the struct is used in a ffi interface. On the one hand, the method can still make modifications to the value, such as first converting a &str to a CString and then storing the *const u8 as the value, which makes the string usable for C. On the other hand, overloading the method also makes it possible to use the names given for it in C instead of writing setValue and getValue, for example. However, as you can see here, one of the two methods does not need a mutable reference to self because it does not change the value field, but because the trait requires it, it is used in both cases anyway. The struct is not only configured and then used as argument in a ffi method, but can also occur as return value of such a method, in which case it will be returned as a immutable reference and should only be read from. The customized trait implementations would look like this

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;
    }
}

Obviously this won't work here because the second impl block doesn't have the same method signature as the trait. I already tried to define the self paramter as another generic parameter in the trait using the arbitrary_self_types features but unfortunately that didn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生寂 2025-02-01 13:40:59

您无法在突变性方面进行参数化。

请参阅:

可以在 self 上参数化,但它将不再是一种方法,只有一个关联的功能:

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 精制的特征实现,这使得可能对精炼 在其实现中的一个特征,即编写一个较少通用的IMP(例如,特征中不安全的安全方法),您也可能能够在将来可以完善可变性(尽管我尚无“看到有关此的讨论),但这只会在您使用具体实例而不是仿制药时放松限制。

一种或另一种方式,我认为这种设计是不正确的。只需使用普通 value() set_value()方法,这很简单且显而易见。

You cannot parameterize over mutability.

See:

You can parameterize on self, but it will not be a method anymore, only an associated 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);
}

Given the draft RFC Refined trait implementations that poses the possibility to refine a trait in its implementation, i.e. to write a less generic impl (e.g. safe method in the impl that is unsafe in the trait), it may be possible that you will be able to refine mutability in the future too (although I haven't seen discussions about that), but that will only relax the restriction when you work with a concrete instance, not with generics.

One way or the other, I don't think this design is correct. Just use normal value() and set_value() methods, it is simple and obvious.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文