gpt4 book ai didi

rust - 为新类型实现 Deref 是否被认为是一种不好的做法?

转载 作者:行者123 更新时间:2023-11-29 07:41:02 25 4
gpt4 key购买 nike

我经常使用 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 and DerefMut were designed specifically to accommodate smart pointers. Because of this, Deref should only be implemented for smart pointers to avoid confusion.

std::ops::Deref


我认为这是不好的做法

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-ahas-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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com