< 返回版块

Pikachu 发表于 2022-01-01 15:20

今天在学习async相关的内容时,注意到rust的method call operator有一些非常甜的语法糖。我猜应该还有人跟我一样不知道这个语法,所以在这里写个帖子分享一下。

通常我们定义一个method的时候,第一个参数是self&self或者&mut self,不会带类型标注。但其实rust允许我们用更复杂的self类型。这里摘抄一下reference里面的例子。(原链接

#![allow(unused)]
fn main() {
use std::rc::Rc;
use std::sync::Arc;
use std::pin::Pin;
// Examples of methods implemented on struct `Example`.
struct Example;
type Alias = Example;
trait Trait { type Output; }
impl Trait for Example { type Output = Example; }
impl Example {
    fn by_value(self: Self) {}
    fn by_ref(self: &Self) {}
    fn by_ref_mut(self: &mut Self) {}
    fn by_box(self: Box<Self>) {}
    fn by_rc(self: Rc<Self>) {}
    fn by_arc(self: Arc<Self>) {}
    fn by_pin(self: Pin<&Self>) {}
    fn explicit_type(self: Arc<Example>) {}
    fn with_lifetime<'a>(self: &'a Self) {}
    fn nested<'a>(self: &mut &'a Arc<Rc<Box<Alias>>>) {}
    fn via_projection(self: <Example as Trait>::Output) {}
}
}

简单来说,你可以使用各种指针类型作为self,只要它最终指向的类型是Self。所有上面这些都被视为method,可以用xxx.yyy()的method syntax来调用。

非常有趣的是,在the book,rust by example和rustlings中都没有提及这一语法糖,只在reference里面可以找到相关说明。我猜测的原因是,多数情况下coercion(Deref和DerefMut)已经足以自动展开智能指针。唯一需要用到这个语法糖的大概就只是Pin这种禁止DerefMut的地方了。

参考链接:

评论区

写评论
linqingyao 2022-01-04 23:53

在《The book》一书中的 Trait Object:https://doc.rust-lang.org/book/ch17-03-oo-design-patterns.html#requesting-a-review-of-the-post-changes-its-state

pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    // --snip--
}

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
}

struct Draft {}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
}

struct PendingReview {}

impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
}
zjhken 2022-01-02 22:02

这个赞!

JasonkayZK 2022-01-02 13:15

挺有趣的

rdigua 2022-01-01 16:34

哈哈 还记得这个into_vec是被编译器检查的时候教会的

--
👇
苦瓜小仔: 标准库里还有一个例外:slice::into_vec

pub fn into_vec<A>(self: Box<[T], A>) -> Vec<T, A>ⓘ
where
    A: Allocator
苦瓜小仔 2022-01-01 16:22

标准库里还有一个例外:slice::into_vec

pub fn into_vec<A>(self: Box<[T], A>) -> Vec<T, A>ⓘ
where
    A: Allocator
1 共 5 条评论, 1 页