我想创建一种在Rust中动态更改对象功能的方法,类似于在CLISP或Groovy等语言中更改MetaObject的方式.

其思想是通过某种类型的接口或指向可变指针的指针向用户(或其他组件)提供黑盒,而可变指针又指向可变 struct .这样,功能的accessing的平均值不会改变,但底层实现可以动态改变(最好是创建一个新 struct ,然后将可变指针指向它,然后销毁旧 struct ).目前,我正试图弄清楚如何做到这一点,同时让借阅判断员满意.

简而言之: {外部(不可变)指针}->{私有可变指针}->{可变(或可替换) struct }

这样做的目的是让人工智能或其他程序有一种手段来动态改进对象或方法,同时保持与程序其余部分的相同接口,这样就不会中断(相同的输入和输出,但底层代码可以改变).

如果你有什么 idea ,请告诉我.

目前正试图让borrow 判断沿着这一点,而调用'println!'.目前得到一个错误,说Mobj没有实现Copy trait.

    #[derive(Debug)]
    struct Mobj {
        str: String
    }

    let mut m_ptr = Mobj {str: String::from("Object 1")};
    let ptr = m_ptr;

    println!("{:?}", m_ptr.str);
    println!("{:?}", ptr.str);

    // Reassign pointer to new object
    let m_ptr = Mobj {str: String::from("Object 2")};
    println!("{:?}", m_ptr.str);
    println!("{:?}", ptr.str); // Call to same, unchanged immutable pointer that points to mutable pointer
    // ^^^^ Still points to old 'Object 1'


    // Now points to the new 'Object 2', but might not be doing exactly what I want it to do.
    let ptr = &m_ptr;
    println!("{:?}", ptr.str);

推荐答案

你想要做的事情在正常的推荐人中是行不通的.

最大的问题是要求具有对可变引用的不可变引用,然后该引用执行一些可变的事情.如果允许,您可以复制不可变引用,然后同时获得对同一对象的多个可变引用,这被认为是未定义的行为.

要实现这一点,您需要某种运行时别名判断.根据您的用例,这将是RefCell(单线程)或Mutex(多线程).这创建了一种称为"内部可变性"的东西,意思是从&&mut的运行时转换. 如果您也不想处理生存期问题,而只是想在程序的多个部分中使用该变量,则可以进一步将其包装在Rc(单线程)或Arc(多线程)中.这并不是必须的,但在许多用例中,这两者是结合使用的.

在我的例子中,我假设你没有线程,因此将使用Rc<RefCell>.

此外,具有一组固定的功能,同时具有替换提供所述功能的实际对象的可能性的用法完全适合trait.然后,您可以将对象存储为Box<dyn Trait>以抽象出真实类型.

use std::{cell::RefCell, rc::Rc};

trait MyTrait {
    fn do_something(&mut self);
}

#[derive(Debug)]
struct Mobj {
    str: String,
}

impl MyTrait for Mobj {
    fn do_something(&mut self) {
        println!("Mobj: \"{}\"", self.str);
    }
}

fn main() {
    let shared_obj: Rc<RefCell<Box<dyn MyTrait>>> = Rc::new(RefCell::new(Box::new(Mobj {
        str: String::from("Object 1"),
    })));

    let second_ref = Rc::clone(&shared_obj);

    second_ref.borrow_mut().do_something();

    *shared_obj.borrow_mut() = Box::new(Mobj {
        str: String::from("Object 2"),
    });

    second_ref.borrow_mut().do_something();
}
Mobj: "Object 1"
Mobj: "Object 2"

当然,你不一定需要Rc,你也可以这样做:

fn main() {
    let shared_obj: RefCell<Box<dyn MyTrait>> = RefCell::new(Box::new(Mobj {
        str: String::from("Object 1"),
    }));

    let second_ref = &shared_obj;

    second_ref.borrow_mut().do_something();

    *shared_obj.borrow_mut() = Box::new(Mobj {
        str: String::from("Object 2"),
    });

    second_ref.borrow_mut().do_something();
}

但你的用例似乎足够复杂,可能会有用.但由你自己决定;)

Rust相关问答推荐

为什么允许我们将可变引用转换为不可变引用?

在UdpSocket上使用sendto时的隐式套接字绑定

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

是否可以使用Rust宏来构建元组的项?

如何在Rust中将选项<;选项<;字符串>;转换为选项<;选项&;str>;?

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

为什么这个变量不需要是可变的?

为什么Rust不支持带关联常量的特征对象?

在Rust内联程序集中使用字符串常量

为什么HashMap::get和HashMap::entry使用不同类型的密钥?

要求类型参数有特定的大小?

提取指向特征函数的原始指针

`use` 和 `crate` 关键字在 Rust 项目中效果不佳

max(ctz(x), ctz(y)) 有更快的算法吗?

是否可以通过可变引用推进可变切片?

为什么数组不像向量那样在 for 块之后移动?

产生拥有值的迭代器的 Rust 可变borrow 在循环中失败

Rustlings 切片原语

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?