gpt4 book ai didi

reference - 如何在您创建的数据需要引用的地方创建工厂函数?

转载 作者:行者123 更新时间:2023-11-29 08:07:38 25 4
gpt4 key购买 nike

在某些情况下,您希望工厂函数创建一些数据,但无论出于何种原因,您返回的数据必须包含引用。这似乎不可能,因为您不能从函数返回引用。

让我们看下面的示例代码:

// Important: traits are of unknown size, and so must be passed around 
// as a reference
trait Shape {
fn area(&self) -> f32;
}
// As seen here.
struct ShapeCollection<'a> {
shapes: Vec<&'a Shape>
}

// This function needs to return a ShapeCollection, but since the
// data structure requires references to work, it seems impossible!
fn make_shapes<'a>(needRectangle: bool, multiplier: f32) -> ShapeCollection<'a> {
let rect = Rectangle {
width: 42.0 * multiplier,
height: 24.0 * multiplier
};
let circle = Circle {
radius: 42.0 * multiplier
};

match needRectangle {
true => ShapeCollection {
shapes: vec![&rect, &circle]
},
false => ShapeCollection {
shapes: vec![&circle]
},
}
}
// ^ This function won't compile because rect and circle do not
// life long enough, and the compiler dies at this point

// Impls if you're interested / want to compile, but not that important
struct Rectangle {
width: f32,
height: f32
}
impl Shape for Rectangle {
fn area(&self) -> f32 {
self.width * self.height
}
}
struct Circle {
radius: f32
}
impl Shape for Circle {
fn area(&self) -> f32 {
(std::f32::consts::PI * self.radius).powf(2f32)
}
}

这是一个基于我正在编写的更复杂代码构建的简化示例。问题的要点是两个混淆的要求:

  • 我需要多态性。因为我为此使用了特征,并且特征没有确定大小,所以 Vec 必须包含引用而不是值
  • 我需要一个工厂函数。由于我想从我的代码的多个部分生成此对象列表但具有不同的参数,因此制作一个封装它的函数是有意义的,而不是复制和粘贴逻辑

如何在 Rust 中解决这两个要求?

这两个选择似乎是:

  • 做一些其他的事情来实现多态性,一些允许作为值传递的东西
  • 以某种不是创建参数化函数的方式删除多个代码块

最佳答案

你只需cannot return a reference to a variable created in a function .

Important: traits are of unknown size, and so must be passed around as a reference

这不是严格意义上的。它们必须通过某种间接方式传递,但引用 (&) 并不是 trait 对象 可以使用的唯一一种间接方式。还有盒装特征对象:

struct ShapeCollection {
shapes: Vec<Box<Shape>>,
}

fn make_shapes(need_rectangle: bool, multiplier: f32) -> ShapeCollection {
let rect = Rectangle {
width: 42.0 * multiplier,
height: 24.0 * multiplier,
};
let circle = Circle {
radius: 42.0 * multiplier,
};

match need_rectangle {
true => ShapeCollection {
shapes: vec![Box::new(rect), Box::new(circle)],
},
false => ShapeCollection {
shapes: vec![Box::new(circle)],
},
}
}

在 99.9% 的情况下,生命周期仅在返回位置的函数签名永远无法工作(或者不做你想做的事)并且应该总是让你暂停:

fn make_shapes<'a>(need_rectangle: bool, multiplier: f32) -> ShapeCollection<'a>

请注意,Rust 样式是 snake_case,所以我重命名为 need_rectangle

另见:

关于reference - 如何在您创建的数据需要引用的地方创建工厂函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49336005/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com