首页 > 解决方案 > 如何使 trait 方法采用 &Self 参数

问题描述

我正在尝试使用一些默认方法实现来创建特征。其中一种方法必须采用相同类型的实例并执行一些计算。

这是我要实现的简单示例:

struct A {
    val: f32,
}

trait S {
    fn val(&self) -> f32;

    fn add(&self, other: &Self) -> f32 {
        add(&self, other)
    }
}

impl S for A {
    fn val(&self) -> f32 {
        self.val
    }
}

fn add<T: S>(first: &T, second: &T) -> f32 {
    first.val() + second.val()
}

这无法编译并出现错误:

15 | |     fn add(&self, other: &Self) -> f32 {
16 | |         add(&self, other)
   | |                    ^^^^^ expected `&Self`, found type parameter `Self`
17 | |     }

我不明白错误信息,因为 other 是&Selfnot类型Self,那么为什么编译器会不这么认为呢?

如果我将其更改为引用add(&self, &other)(这似乎不正确,因为other已经是引用类型),我会收到另一个错误:

   |
16 |         add(&self, &other)
   |         ^^^ the trait `S` is not implemented for `&Self`
...
26 | fn add<T: S>(first: &T, second: &T) -> f32 {
   |           - required by this bound in `add`

有没有办法通过默认特征实现来实现这一点,或者这只适用于具体类型(比如这个问题:如何实现 Add trait for a reference to a struct?)?

编辑:如果我称它为add(self, other),它会尝试发送特征对象,但我想通过引用发送对象。真的,我想发送具体的实现而不是特征对象。

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/main.rs:16:9
   |
16 |         add(self, other)
   |         ^^^ doesn't have a size known at compile-time

标签: rust

解决方案


您正在传递&selfadd(),这使其成为双重引用,并且参数add()类型不一致。Tofadd显然是由第一个参数决定的,这就是为什么编译器似乎期望另一个参数也有参数的原因&&Self。(阅读错误消息末尾的注释。)

调用它,add(self, other)它会编译。请注意,您还需要通过添加来选择退出隐式Sized绑定。add+ ?Sized

// rest as in your code

trait S {
    fn val(&self) -> f32;

    fn add(&self, other: &Self) -> f32 {
        add(self, other)
    }
}

fn add<T: S + ?Sized>(first: &T, second: &T) -> f32 {
    first.val() + second.val()
}

操场


推荐阅读