作者回复: 谢谢夸奖!
作者回复: 很棒! 对于 3,你可以看我的参考代码: ```Rust impl<T> Index<isize> for List<T> { type Output = T; fn index(&self, index: isize) -> &Self::Output { let len = self.len() as isize; // 我们需要先对负数,以及 index 超出范围的数字进行处理 // 使其落在 0..len 之间 let n = (len + index % len) % len; let iter = self.iter(); // 由于 n 一定小于 len 所以这里可以 skip n 取 next // 此时一定有值,所以可以放心 unwrap iter.skip(n as usize).next().unwrap() } } ``` playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9f354aaed64c4b97f3b80c3be9c4b59a
作者回复: 就是如果你获得某个类型T 到其它类型的引用 U,然后又把这个引用 U clone 出一个 U 的带所有权的数据。那么为何不直接实现 From<T> for U 呢?
作者回复: 👍
作者回复: 1. * 代表解引用,&是获取变量引用(地址) 2. trait "继承" 是打引号的继承,只是 trait A "继承" trait B 的方法(和关联类型),是行为的继承,也是一种组合,和面向对象继承的概念是不一样的,它们之间并无数据的继承,也没有类别继承的关系。 3. unwrap() 在示例代码中会常常用到,我在之前的内容中介绍过这样会导致 panic,在生产环境中的代码除非你在上下文中确保它不会 panic,否则不宜使用。
作者回复: 正确!
作者回复: 区别是: let a = &*list; let b = list.deref(); // a == b 注意看 deref 的返回值。
作者回复: DerefMut 依赖 Deref,也就是说要实现 DerefMut 必须县实现 Deref,所以 Target 就复用了。
作者回复: 这里没有额外的 secret,forget 和 ManuallyDrop::new() 不同的地方是一个有返回值,一个没有返回值。文档中的例子也是使用这一点的不同来表示它们不同的使用场景的。你可以再仔细看看两个例子调用 forget 和 ManuallyDrop::new() 的位置的不同,想想为什么使用 forget 不能一开始就调用。:)
作者回复: 👍