目录

水群学习法

云玩家,全靠群友水群时候蹭经验,群友太强啦!

关于Box<dyn Trait>

问题:

这里是box<struct> -> box<dyn trait>, 还是box<struct -> dyn trait>, 如果是后者,运行时怎么拿到size的?

1
2
3
4
5
6
7
8
9
fn thing_factory(thingtype: i32) -> Box<dyn DoThings> {
    if thingtype == 1 {
        return Box::new(MyStruct1 {});
    }
    if thingtype == 2 {
        return Box::new(MyStruct2 {});
    }
    panic!()
}

答案 box<struct> -> box<dyn trait>

土豆: Box<dyn Trait> == *mut dyn Trait == *mut T + *const metadata_of::<T as Trait>()

菜: 编译器会自动吧box<T>包装成box<T + metadate>对吧

土豆: 那是你亲手写的 as

菜: 其实return box<T> 就是 box<T> as box<dyn trait>,这样对吧

土豆: 照说是应该写出来 as _

5大郎: Rust 能有限做 implicit conversion,因为 Rust implicit conversion 是非常少的,但是这里有

对魔忍 | Han: https://blog-1256556944.file.myqcloud.com/public/hanshao.png

关于Variance

协变、逆变、不变 相关背景可以看这篇blog:Rust Subtyping and Variance

疯狂转发到我收藏夹

κόσμος: 假设你有一个 List<Dog>,Dog 是 Animal 的子型,你肯定可以传进 func(x: List<Animal>)

如果这个 func 里修改 List<Animal> 会发生什么?animals.clear(); animals.add(new Cat());

你会发现你的 List<Dog> 里出现了一个 Cat, 这就是为什么在 mutable 下不能 variant

一样的办法,把这个函数想象成另一个函数的参数。一个函数需要一个 callback: fn(Dog)->Ret,那理应是可以传一个 fn(Animal)->Ret 作为这个 callback 的, 因为这个 fn(Animal) -> Ret 一定可以处理 Dog 数据。所以 fn(Animal)->Ret < fn(Dog)->Ret, 而 Dog < Animal,所以函数参数这样的一个型构造是逆变的

nicball: 你可以把fn()→Cat当成fn()→Animal

你可以把fn(Animal)→()当成fn(Cat)→()

所以函数对返回类型协变,对参数类型逆变

或者把他当成getter setter

可以想成读的时候协变,写的时候逆变

那可变的数据结构就只能不变了

屌图

https://blog-1256556944.file.myqcloud.com/public/rust_map_reduce_joker.jpg