#methods #inherit #automatic #macro #field #proc-macro #procedural

inherit-methods-macro

自动从字段继承方法(通过过程宏)

1个不稳定版本

0.1.0 2024年7月1日

2169过程宏

Download history 182/week @ 2024-06-29 9/week @ 2024-07-06 18/week @ 2024-07-13 44/week @ 2024-07-20 49/week @ 2024-07-27

139 每月下载量
用于 ostd

自定义许可

16KB
110

自动从字段继承方法(通过过程宏)。

动机

虽然Rust在某种程度上受到了面向对象编程(OOP)范式的影响,并具有一些典型的OOP特征(如对象、封装和多态),但它不是一门OOP语言。一个证据是缺乏继承,这是OOP的重要支柱。但不要误解我:这种缺乏继承实际上是一件好事,因为它促进了Rust程序中组合优于继承的实践。尽管组合有所有这些好处,Rust程序员仍然必须编写琐碎的转发方法,这是一个繁琐的任务,尤其是当你必须编写很多的时候。

为了解决Rust中使用组合的痛点,该Crate提供了一个方便的过程宏,可以自动为你生成转发方法。换句话说,你的结构体现在可以“继承”来自其字段的方法,享受两全其美的好处:继承的便利性和组合的灵活性。

示例

实现新的类型惯用法

假设你想要创建一个名为Stack<T>的新结构体,它可以通过简单地围绕Vec<T>进行包装并仅公开Vec的子集API来实现。以下是这个Crate如何帮助你轻松完成这个任务的示例。

 use inherit_methods_macro::inherit_methods;
 pub struct Stack<T>(Vec<T>);

 // Annotate an impl block with #[inherit_methods(from = "...")] to enable automatically
 // inheriting methods from a field, which is specifiedd by the from attribute.
 #[inherit_methods(from = "self.0")]
 impl<T> Stack<T> {
     // Normal methods can be implemented with inherited methods in the same impl block.
     pub fn new() -> Self {
         Self(Vec::new())
     }

     // All methods without code blocks will "inherit" the implementation of Vec by
     // forwarding their method calls to self.0.
     pub fn push(&mut self, value: T);
     pub fn pop(&mut self) -> Option<T>;
     pub fn len(&self) -> usize;
 }

如果你想要为包装类型派生常见特性(如AsRefDeref),请查看shrinkwraprs crate。

模拟经典的OOP继承

在许多面向对象编程框架或应用程序中,拥有一个所有对象从中继承的基础类非常有用。在这个例子中,我们希望做同样的事情,创建一个基础类(用于接口的 Object 特性和用于实现的 ObjectBase 结构体),这样所有对象都应该“继承”。

use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Mutex;

use inherit_methods_macro::inherit_methods;

pub trait Object {
    fn type_name(&self) -> &'static str;
    fn object_id(&self) -> u64;
    fn name(&self) -> String;
    fn set_name(&self, new_name: String);
}

struct ObjectBase {
    object_id: u64,
    name: Mutex<String>,
}

impl ObjectBase {
    pub fn new() -> Self {
        static NEXT_ID: AtomicU64 = AtomicU64::new(0);
        Self {
            object_id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
            name: Mutex::new(String::new()),
        }
    }

    pub fn object_id(&self) -> u64 {
        self.object_id
    }

    pub fn name(&self) -> String {
        self.name.lock().unwrap().clone()
    }

    pub fn set_name(&self, new_name: String) {
        *self.name.lock().unwrap() = new_name;
    }
}

struct DummyObject {
    base: ObjectBase,
}

impl DummyObject {
    pub fn new() -> Self {
        Self {
            base: ObjectBase::new(),
        }
    }
}

#[inherit_methods(from = "self.base")]
impl Object for DummyObject {
    // Give this method an implementation specific to this type
    fn type_name(&self) -> &'static str {
        "DummyObject"
    }

    // Inherit methods from the base class
    fn object_id(&self) -> u64;
    fn name(&self) -> String;
    fn set_name(&self, new_name: String);
}

依赖关系

~2MB
~43K SLoC