- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我经常使用 newtype 模式,但我厌倦了编写 my_type.0.call_to_whatever(...)
。我很想实现 Deref
特性,因为它允许编写更简单的代码,因为在某些情况下我可以使用我的新类型,就好像它是底层类型一样,例如:
use std::ops::Deref;
type Underlying = [i32; 256];
struct MyArray(Underlying);
impl Deref for MyArray {
type Target = Underlying;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let my_array = MyArray([0; 256]);
println!("{}", my_array[0]); // I can use my_array just like a regular array
}
这是好事还是坏事?为什么?缺点是什么?
最佳答案
the rules regarding
Deref
andDerefMut
were designed specifically to accommodate smart pointers. Because of this,Deref
should only be implemented for smart pointers to avoid confusion.
我认为这是不好的做法。
since I can use my newtype as if it were the underlying type in some situations
这就是问题所在 — 它可以隐式用作基础类型无论何时引用。如果你实现 DerefMut
,那么它也适用于需要可变引用的情况。
您无法控制基础类型中可用的内容和不可用的内容;一切都是。在你的例子中,你想让人们调用 as_ptr
?怎么样 sort
?我当然希望你这样做,因为他们可以!
您所能做的就是尝试覆盖方法,但它们仍然必须存在:
impl MyArray {
fn as_ptr(&self) -> *const i32 {
panic!("No, you don't!")
}
}
即便如此,它们仍然可以被显式调用(<[i32]>::as_ptr(&*my_array);
)。
我认为这是不好的做法,原因与我认为使用继承来重用代码是不好的做法是一样的。在您的示例中,您实际上是从数组继承的。我永远不会写像下面这样的 Ruby:
class MyArray < Array
# ...
end
这又回到了面向对象建模中的is-a 和has-a 概念。是MyArray
数组?它应该能够在数组可以使用的任何地方使用吗?它是否具有对象应支持消费者不应该破坏的先决条件?
but I am tired of writing
my_type.0.call_to_whatever(...)
与其他语言一样,我认为正确的解决方案是组合而不是继承。如果您需要转接电话,请在新类型上创建一个方法:
impl MyArray {
fn call_to_whatever(&self) { self.0.call_to_whatever() }
}
在 Rust 中造成这种痛苦的主要原因是缺少委托(delegate)。 假设的委托(delegate)语法可能类似于
impl MyArray {
delegate call_to_whatever -> self.0;
}
在等待一流委托(delegate)时,我们可以使用类似 delegate 的箱子或 ambassador以帮助填补一些空白。
那么什么时候应该使用Deref
/DerefMut
?我提倡只有在您实现智能指针时才有意义。
实际上,我确实使用Deref
/DerefMut
对于在我是唯一或主要贡献者的项目中未公开的新类型。这是因为我相信自己并且非常了解我的意思。如果存在委托(delegate)语法,我不会。
关于rust - 为新类型实现 Deref 是否被认为是一种不好的做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45086595/
我正在阅读 Rust 的 Deref 文档特点: pub trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Ta
下面是Deref example from The Rust Programming Language除了我添加了另一个断言。 为什么 assert_eq 和 deref 也等于 'a'?为什么在手动
我想实现 Deref和 DefrefMut在拥有盒装特征的结构上,例如: use std::ops::{Deref, DerefMut}; trait Quack { fn quack(&se
这个问题在这里已经有了答案: Why is the return type of Deref::deref itself a reference? (2 个回答) 1年前关闭。 例如,我有一个实现了
来自 clojure 为勇敢而真实的人: (defmacro enqueue [q concurrent-promise-name & work] (let [concurrent (butl
我正在传递一个链表,其中包含另一个链表到一个函数,但我在从传递的双指针中取消/引用内部链表时遇到问题。 push(*config->inner_linked_list... 行的编译器错误是 '*co
我正在尝试为枚举实现Deref: use std::rc::Rc; use std::ops::Deref; pub trait tObject { fn name(&self) -> Str
我需要为来自外部 crate 的对象实现 fmt::Display 方法,因此我为该对象创建了一个包装器。我希望能够使用原始对象的所有方法,而不必重新定义所有方法。我尝试按照很棒的 IRC chann
这个问题在这里已经有了答案: Why is the return type of Deref::deref itself a reference? (2 个答案) 关闭 5 年前。 以下代码: us
我有: struct Id; struct Url; struct IdAndUrl { id: Id, url: Url, } 我希望能够使用 IdAndUrl在我需要的地方 Id
我经常使用 newtype 模式,但我厌倦了编写 my_type.0.call_to_whatever(...)。我很想实现 Deref 特性,因为它允许编写更简单的代码,因为在某些情况下我可以使用我
我在 Rust 中编写一个 Vector 类只是为了好玩,我认为能够为它实现 Deref 会很好,就像访问元组引用一样访问它。例如,Vec2可以取消引用为 &(f32, f32) .我想到了这个: p
如果能够使用 Deref 从通用容器生成 &TraitType,而不是调用 instance.as_ref() 会更方便。即: (*my_container).do_thing(); 对比 my_co
在这段代码之前,我以为我了解了移动语义。 fn main() { let v = Data { body: vec![10, 40, 30], }; p(&v)
我有一个实现Deref的结构: pub struct Foo { val: u8, } impl Deref for Foo { type Target = u8; fn de
class DogOwner { Dog dog; DogOwner(Dog dog) { this.dog = dog; } } class Dog {
我在尝试将 impl Add for String 添加到标准库时遇到了这个问题。但是我们可以轻松复制它,无需运算符(operator)恶作剧。我们从这个开始: trait MyAdd { f
在阅读了关于 Smart Pointers and Interior mutability 的 Rust 书中的部分之后,作为个人练习,我尝试编写一个函数,该函数将遍历智能指针的链表并返回列表中的“最
这里是 example of usage Deref 的修改版本: use std::ops::Deref; use std::rc::Rc; #[derive(Clone, PartialEq, H
我有一个 String newtype ErrorMessage 我在原型(prototype)箱中用于错误。 (我知道这是一种不好的做法。我将在发布之前构建一组适当的不同错误类型。) 我需要 Err
我是一名优秀的程序员,十分优秀!