[英]Rust - Same Type different behaviour
就我的理解而言,泛型允許在不同類型之間共享相同的行為。 為實例,
trait Bird {}
struct BirdFly {}
impl Bird for BirdFly {
pub fn fly() -> can fly
}
struct BirdCanntFly {}
impl Bird for BirdCanntFly{
pub fn fly() -> cannt fly
}
let birds = vec![
Box::new(BirdFly{}), // allow this bird to fly, for instance
Box::new(BirdCanntFly{}), // dont't allow this bird to fly
];
我的問題是相反的,即是否有可能讓相同的類型采取不同的行為(沒有 ifs、enums 或 Box)。在這個例子中,在兩種類型(BirdFly 和 BirdCanntFly)維度相同,只是行為不同。 就像是:
struct Bird {
fly: // associate different behavior
}
let birds = vec![
Bird{ fly: some_fly_behavior }, // allow this bird to fly, for instance
Bird{ fly: another_fly_behavior }, // dont't allow this bird to fly
];
birds[0].fly();
birds[1].fly();
如果 fly 收到相同的參數並返回相同的類型,我看不出問題的原因。 此外,通過這種方式,我可以擺脫矢量內的 Box。 特別是因為我可能在向量中有數百萬個元素並且被多次迭代訪問,這樣我就可以避免開銷。 謝謝您的幫助!
您可以將函數指針存儲在struct Bird
並添加一個輔助方法來獲得您想要的語法。
struct Bird {
name: String,
fly_impl: fn(&Bird) -> (),
}
impl Bird {
fn new(name: String, fly_impl: fn(&Bird) -> ()) -> Bird {
Bird { name, fly_impl }
}
fn fly(self: &Bird) {
(self.fly_impl)(self)
}
}
fn behavior1(b: &Bird) {
println!("{} behavior1", b.name);
}
fn behavior2(b: &Bird) {
println!("{} behavior2", b.name);
}
fn main() {
let captured_variable = 10;
let birds = vec![
Bird::new("Bird1".into(), behavior1),
Bird::new("Bird2".into(), behavior2),
Bird::new("Bird3".into(), |b| println!("{} lambda", b.name)),
/*Bird::new("Bird4".into(), |b| {
println!("{} lambda with {}", b.name, captured_variable)
}),*/
];
(birds[0].fly_impl)(&birds[0]);
for bird in birds {
bird.fly();
}
}
不要將fn
與trait Fn
混淆。 前者只允許函數和非捕獲 lambdas 並且具有固定大小。 后者允許任意大小的任意捕獲,因此需要一些像Box
間接。 兩者都在調用時進行動態調度。
請注意Bird3
的行為如何由非捕獲 lambda 指定,這是允許的。 但是,如果您嘗試取消對Bird4
的注釋,該示例將無法編譯,因為其所需的行為是捕獲 lambda,它通常會變得任意大,並且我們已經禁止Box
es 和其他間接方式。
我對 Rust 的了解不夠多,無法告訴您是否有更類似於 Rust 的解決方案。 但是,您的情況非常具體:
Bird
層次結構。 否則enum
更適合。Bird
都具有完全相同的一組字段和trait
支持。 否則,您必須通過Box<dyn Bird>
使用trait
和標准動態調度。Bird
分配堆。 否則,您可以使用trait
和標准動態調度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.