rust - 如何在结构上实现“方法覆盖”(将闭包传递给结构?)
问题描述
我是 Rust 的新手,仍在学习如何用该语言表示不同的设计模式,而且我最近的背景都是严重的 OO 设计,这无助于思考这个问题。
在下面的示例中,我想将sort_ascending
条件消除为更优雅的东西,理想情况下让它在编译时完全解决。
struct MyList {
ladder: Vec<i32>,
sort_ascending: bool,
}
impl MyList {
pub fn new(data: &[i32], sort_ascending: bool) -> MyList {
return MyList {
ladder: data.to_vec(),
sort_ascending: sort_ascending,
};
}
pub fn get_best(&self) -> Option<&i32> {
if self.sort_ascending {
return self.ladder.iter().reduce(|a, b| if a >= b { a } else { b });
} else {
return self.ladder.iter().reduce(|a, b| if a <= b { a } else { b });
}
}
}
fn main() {
let x = MyList::new(&[10, 4, 30, 2, 5, 2], true);
let r = x.get_best();
println!("{:?}", r);
let x = MyList::new(&[10, 4, 30, 2, 5, 2], false);
let r = x.get_best();
println!("{:?}", r);
}
我认为解决方案在于将闭包传递给reduce()
可配置的,并尝试了以下几行的许多变体,但均未成功:
struct MyList<F>
where F : Fn(i32,i32) -> i32
{
ladder: Vec<i32>,
sort_closure : F
}
impl<F> MyList<F>
where F : Fn(i32,i32) -> i32
{
pub fn new(data: &[i32], sort_ascending: bool) -> MyList<F> {
if sort_ascending {
return MyList {
ladder: data.to_vec(),
sort_closure : |a, b| if a >= b { a } else { b },
};
} else {
return MyList {
ladder: data.to_vec(),
sort_closure : |a, b| if a <= b { a } else { b },
};
}
}
pub fn get_best(&self) -> Option<&i32> {
return self.ladder.iter().reduce(self.sort_closure);
}
}
fn main() {
let x = MyList::new(&[10, 4, 30, 2, 5, 2], true);
let r = x.get_best();
println!("{:?}", r);
let x = MyList::new(&[10, 4, 30, 2, 5, 2], false);
let r = x.get_best();
println!("{:?}", r);
}
我真的很感激任何关于如何使上述代码编译的指针,或者指向实现这种模式的正确方法的指针。
解决方案
一个直接的解决方法是使用函数指针 ( fn
) 而不是尝试在 上使用泛型参数MyList
。
以下解决方案类似于用户 Jmb 在上述评论中建议的解决方案,但通过进一步简化
- 避免函数指针中的生命周期
- 使用
std::cmp::{max, min}
而不是编写我们自己的闭包(尽管如果您像以前一样自己定义闭包,代码仍然有效)
use std::cmp;
struct MyList {
ladder: Vec<i32>,
sort_closure: fn(i32, i32) -> i32,
}
impl MyList {
pub fn new(data: &[i32], sort_ascending: bool) -> MyList {
MyList {
ladder: data.to_vec(),
sort_closure: match sort_ascending {
true => cmp::max,
false => cmp::min,
},
}
}
pub fn get_best(&self) -> Option<i32> {
self.ladder.iter().copied().reduce(self.sort_closure)
}
}
为什么原始方法不起作用
这就是MyList
定义的样子:
struct MyList<F>
where F : Fn(i32,i32) -> i32
{
ladder: Vec<i32>,
sort_closure : F
}
这不起作用的原因与 on 的类型参数F
有关MyList
。在那里拥有类型参数意味着调用者(中的代码main()
)可以自由地用他们选择MyList<F>
的任何F
满足Fn(i32,i32) -> i32
约束的实例进行实例化。但是,在MyList::new()
函数内部,我们定义了自己的两个闭包,然后尝试将其中一个存储在MyList
. 这就是矛盾。调用者无法选择要存储的闭包类型,除非间接使用sort_ascending
标志。
推荐阅读
- apache-kafka - Kafka - 单一生产者 - 单一消费者 - 多个分区,只有一个副本
- logstash - 由于错误,Logstash 停止处理:(SystemExit) exit org.jruby.exceptions.SystemExit
- python - 如何让多个对象在python中引用同一个对象
- angular - 对我的可重用表格组件使用 ng-content 隐藏了行分组和可见性等功能,并且在数据之后也显示没有可用的数据
- julia - Julia中浮点运算的速度
- python - 给定一个纯文本和一个可能的密文,确定密文是否可以使用上述方案从纯文本形成
- node.js - 我们可以在电子 js 上禁用键盘输入吗
- python - 有没有办法根据键盘输入改变玩家面对的方向?Pyglet, Cocos2d
- c++ - 如何使用 g++ 在 c++ 20 中使用模块?
- sql - 加入日期到日期范围 SQL