Vector 如何取消包含在多态向量中的元素的装箱?
阅读后,它看起来像生锈自动拆箱。是这样吗 我的代码没有编译,我不明白答案的代码是如何编译的 对于包含装箱特征的多态性载体,取消装箱的正确方法是什么 我已经读过并且没有看到任何类似于Vector 如何取消包含在多态向量中的元素的装箱?,vector,rust,boxing,Vector,Rust,Boxing,阅读后,它看起来像生锈自动拆箱。是这样吗 我的代码没有编译,我不明白答案的代码是如何编译的 对于包含装箱特征的多态性载体,取消装箱的正确方法是什么 我已经读过并且没有看到任何类似于unbox()的方法 我的代码是: trait HasArea { fn area(&self) -> f64; } struct Circle { x: f64, y: f64, radius: f64, } impl HasArea for Circle {
unbox()
的方法
我的代码是:
trait HasArea {
fn area(&self) -> f64;
}
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct Square {
x: f64,
y: f64,
side: f64,
}
impl HasArea for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn print_area<T: HasArea>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
print_area(c);
print_area(s);
let vec: Vec<Box<HasArea>> = Vec::new();
vec.push(Box::new(c));
vec.push(Box::new(s));
for x in vec {
print_area(x)
}
}
trait区域{
fn区域(自身)->f64;
}
结构圆{
x:f64,
y:f64,
半径:f64,
}
圆的面积{
fn区域(自身)->f64{
std::f64::consts::PI*(self.radius*self.radius)
}
}
结构广场{
x:f64,
y:f64,
侧面:f64,
}
广场面积{
fn区域(自身)->f64{
自我侧,自我侧
}
}
fn打印区域(形状:T){
println!(“此形状的面积为{}”,shape.area());
}
fn main(){
设c=圆{
x:0.0f64,
y:0.0f64,
半径:1.0f64,
};
让s=平方{
x:0.0f64,
y:0.0f64,
侧面:1.0f64,
};
打印区(c);
打印区;
让vec:vec=vec::new();
向量推送(Box::new(c));
矢量推送(框:新);
对于向量中的x{
打印区域(x)
}
}
我的错误是:
编译rustgraph v0.1.0(file:///home/chris/lunch/rustgraph)
错误[E0277]:未满足特征绑定'Box:HasArea'
-->src/main.rs:54:9
|
54 |打印面积(x)
|^^^^^^^^^^^^未为` Box'实现特性'HasArea'`
|
=注:“打印”区域需要`
您可以像print\u area(*x)
那样取消对它的引用,但由于其他原因,它将不起作用:为print\u area
参数绑定的大小。函数需要知道其参数的大小
您的代码中还有其他问题:您试图推入一个不可变的向量,并且试图将移动的值装箱。在print\u area()
中使用后,这些已被移动
我的意见是,将print\u area
作为一种采用不可变引用的方法会更容易。这将如您所期望的那样工作
trait HasArea {
fn area(&self) -> f64;
fn print_area(&self) {
println!("This shape has area of {}", self.area());
}
}
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct Square {
x: f64,
y: f64,
side: f64,
}
impl HasArea for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn print_area<T: HasArea>(shape: &T) {
println!("This shape has an area of {}", shape.area());
}
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
c.print_area();
s.print_area();
let mut vec: Vec<Box<HasArea>> = Vec::new();
vec.push(Box::new(c));
vec.push(Box::new(s));
for x in vec {
x.print_area();
}
}
trait区域{
fn区域(自身)->f64;
fn打印区域(自身(&S){
println!(“此形状的面积为{}”,self.area());
}
}
结构圆{
x:f64,
y:f64,
半径:f64,
}
圆的面积{
fn区域(自身)->f64{
std::f64::consts::PI*(self.radius*self.radius)
}
}
结构广场{
x:f64,
y:f64,
侧面:f64,
}
广场面积{
fn区域(自身)->f64{
自我侧,自我侧
}
}
fn打印区域(形状:&T){
println!(“此形状的面积为{}”,shape.area());
}
fn main(){
设c=圆{
x:0.0f64,
y:0.0f64,
半径:1.0f64,
};
让s=平方{
x:0.0f64,
y:0.0f64,
侧面:1.0f64,
};
c、 打印区域();
s、 打印区域();
让mut-vec:vec=vec::new();
向量推送(Box::new(c));
矢量推送(框:新);
对于向量中的x{
x、 打印区域();
}
}
阅读后,看起来锈会自动拆箱。是这样吗
不像你想象的那么自动。实际上,您正在寻找unbox
方法,而Box
为目标T
实现Deref
。这意味着您应该将调用为_ref()
或依赖Deref
强制。请注意,T
对于未分级的类型是不可能的,因为您依赖多态类型,所以使用者函数必须接受引用
我擅自修复了main
和print\u区域
,使其正常工作。该向量也被不正确地声明为不可变
fn print_area<T: HasArea + ?Sized>(shape: &T) {
println!("This shape has an area of {}", shape.area());
}
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
print_area(&c);
print_area(&s);
let mut vec: Vec<Box<HasArea>> = Vec::new();
vec.push(Box::new(c));
vec.push(Box::new(s));
for x in vec {
print_area(&*x)
}
}
fn打印区域(形状:&T){
println!(“此形状的面积为{}”,shape.area());
}
fn main(){
设c=圆{
x:0.0f64,
y:0.0f64,
半径:1.0f64,
};
让s=平方{
x:0.0f64,
y:0.0f64,
侧面:1.0f64,
};
打印区域(&c);
打印区域(&s);
让mut-vec:vec=vec::new();
向量推送(Box::new(c));
矢量推送(框:新);
对于向量中的x{
打印区域(&*x)
}
}
作为E_net4建议的替代方案,您可以使用带有参考的Vec
,而不是将您的特征装箱:
fn print_area<T: HasArea+?Sized>(shape: &T) {
println!("This shape has an area of {}", shape.area());
}
let mut vec: Vec<&HasArea> = Vec::new();
vec.push(&c);
vec.push(&s);
for x in vec {
print_area(x)
}
fn打印区域(形状:&T){
println!(“此形状的面积为{}”,shape.area());
}
让mut-vec:vec=vec::new();
向量推送(&c);
向量推送(&s);
对于向量中的x{
打印区域(x)
}
要回答您的直接问题:
如何取消包含在多态向量中的元素的装箱
您不能。一旦某个东西被装箱并删除了混凝土类型,就这样了。无法将框
制作回SomeConcreteType
,因为没有人知道该具体类型是什么
要解决代码中的问题。。。再次检查错误消息:
特征绑定框:HasArea
不满足
那是因为引用了一个特征(或者一个特征的盒子)
为了让您的程序能够按照您最初编写的方式编译和运行,您只需要实现trait for box,我们也可以执行引用:
impl<T: ?Sized> HasArea for Box<T>
where T: HasArea
{
fn area(&self) -> f64 { (**self).area() }
}
impl<'a, T: ?Sized> HasArea for &'a T
where T: HasArea
{
fn area(&self) -> f64 { (**self).area() }
}
impl HasArea for Box
其中T:HasArea
{
fn区域(&self)->f64{(**self.area()}
}
impl f64{(**self).area()}
}
这允许您的固定主管道运行:
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
print_area(&c);
print_area(&s);
let vec: Vec<Box<HasArea>> = vec![Box::new(c), Box::new(s)];
for x in vec {
print_area(x)
}
}
fn main(){
设c=圆{
x:0.0f64,
y:0.0f64,
半径:1.0f64,
};
让s=平方{
x:0.0f64,
y:0.0f64,
侧面:1.0f64,
};
打印区域(&c);
打印区域(&s);
让vec:vec=vec![Box::new(c),Box::new(s)];
对于向量中的x{
打印区域(x)
}
}
这里,我们将c
和s
的引用传递到print\u区域
,以避免