rust - 有没有一种内存有效的方法来更改固有实现的行为?

标签 rust

有没有一种内存有效的方法来更改固有实现上的行为?目前,我可以通过存储许多函数指针来完成行为更改,然后由固有实现调用这些函数指针。我的困难在于,可能存在大量此类功能以及大量依赖于这些功能的对象,因此,我想减少使用的内存量。作为示例,请考虑以下代码:

// Holds the data for some process
struct MyData {
    x: f64,
    y: f64,
    fns: MyFns,
}
impl MyData {
    // Create a new object
    fn new(x: f64, y: f64) -> MyData {
        MyData {
            x,
            y,
            fns: CONFIG1,
        }
    }

    // One of our functions
    fn foo(&self) -> f64 {
        (self.fns.f)(self.x, self.y)
    }

    // Other function
    fn bar(&self) -> f64 {
        (self.fns.g)(self.x, self.y)
    }
}

// Holds the functions
struct MyFns {
    f: fn(x: f64, y: f64) -> f64,
    g: fn(x: f64, y: f64) -> f64,
}

// Some functions to use
fn add(x: f64, y: f64) -> f64 {
    x + y
}
fn sub(x: f64, y: f64) -> f64 {
    x - y
}
fn mul(x: f64, y: f64) -> f64 {
    x * y
}
fn div(x: f64, y: f64) -> f64 {
    x / y
}

// Create some configurations
const CONFIG1: MyFns = MyFns {
    f: add,
    g: mul,
};
const CONFIG2: MyFns = MyFns {
    f: sub,
    g: div,
};

fn main() {
    // Create our structure
    let mut data = MyData::new(1., 2.);

    // Check our functions
    println!(
        "1: x={}, y={}, foo={}, bar={}",
        data.x,
        data.y,
        data.foo(),
        data.bar()
    );

    // Change the functions
    data.fns = CONFIG2;

    // Print the functions again
    println!(
        "2: x={}, y={}, foo={}, bar={}",
        data.x,
        data.y,
        data.foo(),
        data.bar()
    );

    // Change a single function
    data.fns.f = add;

    // Print the functions again
    println!(
        "3: x={}, y={}, foo={}, bar={}",
        data.x,
        data.y,
        data.foo(),
        data.bar()
    );
}
此代码允许通过编辑foobar来更改fg的行为。但是,它也不灵活。我宁愿使用装箱的特征对象Box<dyn Fn(f64,f64)->f64,但是之后我无法创建一些默认配置(例如CONFIG1CONFIG2),因为Box不能用于创建常量对象。另外,如果我们有大量的函数和对象,我想为它们的实现共享内存。对于函数指针来说,这没什么大不了的,但是对于闭包来说,它却是。在这里,我们无法为配置创建常量Rc来共享内存。最后,我们可以静态引用某个配置,这样可以节省内存,但是之后我们就无法更改各个功能。我宁愿遇到这样一种情况,在大多数情况下,我们为这些功能共享内存,但是有能力保留自己的内存并根据需要更改功能。
如果可以的话,我愿意提供更好的设计。最终,我想基于foo内部以某种形式或另一种形式持有的函数在运行时更改barMyData的行为。此外,我想提供一种在可能的情况下共享内存的方法,并且我们能够更改单个功能,而不仅仅是整个配置。

最佳答案

一个简单的dyn引用将在这里工作-它允许引用具有特定特征但类型仅在运行时已知的对象。
(这正是您想要的函数指针。将其视为每个函数都有其自己的特殊类型,但是属于Fn(f64,f64)->f64之类的特性。)
因此,您的结构可以定义为:

struct MyData<'a> {
    x: f64,
    y: f64,
    f: &'a dyn Fn(f64, f64) -> f64,
    g: &'a dyn Fn(f64, f64) -> f64,
}
(注意,您需要生命周期说明符'a,以确保该引用的生命周期不短于结构本身。)
然后,您的展示次数可能像:
impl<'a> MyData<'a> {
    // Create a new object
    fn new(x: f64, y: f64) -> Self {
        MyData {
            x,
            y,
            f: &add, // f and g as in CONFIG1
            g: &mul,
        }
    }

    fn foo(&self) -> f64 {
        (self.f)(self.x, self.y)
    }

    // etc...
}
根据您希望默认配置的工作方式,您可以将它们配置为更多固有函数(例如fn to_config2(&mut self);),也可以仅使用函数指针创建单独的结构,然后具有将这些函数指针复制到MyData结构中的函数。

关于rust - 有没有一种内存有效的方法来更改固有实现的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62523879/

相关文章:

rust - 如何获得impl Trait使用适当的生存期来对其中包含另一个生存期的值进行可变引用?

rust - 为什么AtomicUsize的fetch_max返回的值大于其参数?

memory - 了解 Rust 中的 Rc 内存泄漏

rust - 为什么使用带有 into 的涡轮鱼会给出 "wrong number of type arguments"?

rust - 如何将特质对象的Vec变成树形结构?

rust - 通过引用传递字符串并操作字符串

rust - 返回对捕获的可变变量的引用

vector - 用任何类型的元组定义向量

input - 如何从输入中读取单个字符作为 u8?

rust - 当 `Box<dyn MyTrait>` 具有参数化类型时,如何保存 `MyTrait` ?