【问题标题】:What types are valid for the `self` parameter of a method?哪些类型对方法的 `self` 参数有效?
【发布时间】:2014-08-23 14:24:23
【问题描述】:

我想创建一个仅在self 参数为Rc 时才有效的方法。我看到我可以使用Box,所以我想我可以尝试模仿它的工作原理:

use std::rc::Rc;
use std::sync::Arc;

struct Bar;

impl Bar {
    fn consuming(self) {}
    fn reference(&self) {}
    fn mutable_reference(&mut self) {}
    fn boxed(self: Box<Bar>) {}
    fn ref_count(self: Rc<Bar>) {}
    fn atomic_ref_count(self: Arc<Bar>) {}
}

fn main() {}

产生这些错误:

error[E0308]: mismatched method receiver
  --> a.rs:11:18
   |
11 |     fn ref_count(self: Rc<Bar>) {}
   |                  ^^^^ expected struct `Bar`, found struct `std::rc::Rc`
   |
   = note: expected type `Bar`
   = note:    found type `std::rc::Rc<Bar>`

error[E0308]: mismatched method receiver
  --> a.rs:12:25
   |
12 |     fn atomic_ref_count(self: Arc<Bar>) {}
   |                         ^^^^ expected struct `Bar`, found struct `std::sync::Arc`
   |
   = note: expected type `Bar`
   = note:    found type `std::sync::Arc<Bar>`

这是 Rust 1.15.1。

【问题讨论】:

    标签: methods syntax rust


    【解决方案1】:

    在 Rust 1.33 之前,只有四个有效的方法接收器:

    struct Foo;
    
    impl Foo {
        fn by_val(self: Foo) {} // a.k.a. by_val(self)
        fn by_ref(self: &Foo) {} // a.k.a. by_ref(&self)
        fn by_mut_ref(self: &mut Foo) {} // a.k.a. by_mut_ref(&mut self)
        fn by_box(self: Box<Foo>) {} // no short form
    }
    
    fn main() {}
    

    Originally,Rust 没有这种显式的self 形式,只有self&amp;self&amp;mut self~selfBox 的旧名称)。这改变了,只有按值和按引用具有简写的内置语法,因为它们是常见的情况,并且具有非常关键的语言属性,而所有智能指针(包括Box)都需要显式形式.

    从 Rust 1.33 开始,some additional selected types 可用作 self

    • Rc
    • Arc
    • Pin

    这意味着原来的例子现在可以工作了:

    use std::{rc::Rc, sync::Arc};
    
    struct Bar;
    
    impl Bar {
        fn consuming(self)                  { println!("self") }
        fn reference(&self)                 { println!("&self") }
        fn mut_reference(&mut self)         { println!("&mut self") }
        fn boxed(self: Box<Bar>)            { println!("Box") }
        fn ref_count(self: Rc<Bar>)         { println!("Rc") }
        fn atomic_ref_count(self: Arc<Bar>) { println!("Arc") }
    }
    
    fn main() {
        Bar.consuming();
        Bar.reference();
        Bar.mut_reference();
        Box::new(Bar).boxed();
        Rc::new(Bar).ref_count();
        Arc::new(Bar).atomic_ref_count();
    }
    

    但是,impl 处理尚未完全通用以匹配语法,因此用户创建的类型仍然不起作用。在功能标志arbitrary_self_types 下正在取得进展,并在the tracking issue 44874 中进行讨论。

    (值得期待!)

    【讨论】:

    • 所以我可以合理地期待除Box 之外的其他库类型将在未来的某个时候得到支持?
    • 是的,支持其他指针类型是语法变化的主要动机。
    • 几个月后回到这个;你知道这方面有什么变化吗?代码原样无法编译,所以还没有什么明显的。
    • @Shepmaster 在下面看到我的答案。
    • 除了例如Arc, self 也可以是 &Arc 或 &mut Arc。可能大多数用例只喜欢 &T,但也许有些方法想克隆 T 所在的 Arc。
    【解决方案2】:

    现在可以为self 使用任意类型,包括Arc&lt;Self&gt;,但该功能被认为不稳定,因此需要添加此crate attribute

    #![feature(arbitrary_self_types)]
    

    使用feature crate 属性需要使用 nightly Rust。

    【讨论】:

    • 我要补充一点,尽管有名称,但任意自我类型并不是完全“任意”的,而是必须(传递地)引用到 Self。所以self: Arc&lt;Self&gt;self: &amp;Arc&lt;Self&gt; 很好,但self: Vec&lt;Self&gt; 不是。 (当然细节在稳定之前可能会有所变化。)
    • 这个答案现在已经过时了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 2016-08-31
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多