且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-11-16 12:51:22

我认为这是不良做法


因为在某些情况下我可以使用新类型,就好像它是基础类型一样

since I can use my newtype as if it were the underlying type in some situations

这就是问题所在–只要有引用,它就可以隐式用作基础类型 。如果实现 DerefMut ,那么它在需要可变引用时也适用。

That's the problem — it can be implicitly used as the underlying type whenever a reference is. If you implement DerefMut, then it also applies when a mutable reference is needed.

您没有任何引用控制基础类型的可用和不可用;一切都是。在您的示例中,您是否要允许人们呼叫 as_ptr sort 怎么样? > ?我肯定希望您能这样做,因为它们可以!

You don't have any control over what is and what is not available from the underlying type; everything is. In your example, do you want to allow people to call as_ptr? What about sort? I sure hope you do, because they can!

关于您所能做的就是尝试覆盖方法,但它们仍然必须存在:

About all you can do is attempt to overwrite methods, but they still have to exist:

impl MyArray {
    fn as_ptr(&self) -> *const i32 {
        panic!("No, you don't!")
    }
}

即使如此,它们仍然可以显式调用(< [i32]> :: as_ptr(& * my_array); )。

Even then, they can still be called explicitly (<[i32]>::as_ptr(&*my_array);).

出于同样的原因,我认为使用继承进行代码重用是一种不好的做法,因此我认为这是不好的做法。在您的示例中,您实质上是从数组继承。我绝不会写类似以下Ruby的代码:

I consider it bad practice for the same reason I believe that using inheritance for code reuse is bad practice. In your example, you are essentially inheriting from an array. I'd never write something like the following Ruby:

class MyArray < Array
  # ...
end

这回到 is-a has-a 概念。是 MyArray 一个数组吗?应该可以在数组可以使用的任何地方使用它们吗?它是否有先决条件,那就是对象应该坚持消费者不应该能够破坏?

This comes back to the is-a and has-a concepts from object-oriented modeling. Is MyArray an array? Should it be able to be used anywhere an array can? Does it have preconditions that the object should uphold that a consumer shouldn't be able to break?


但是我对写 my_type.0.call_to_whatever(...)

就像其他语言一样,我相信正确的解决方案是组成而不是继承。如果您需要转接呼叫,请在新类型上创建一个方法:

Like in other languages, I believe the correct solution is composition over inheritance. If you need to forward a call, create a method on the newtype:

impl MyArray {
    fn call_to_whatever(&self) { self.0.call_to_whatever() } 
}

使Rust痛苦的是缺少代理假设的委托语法可能类似于

The main thing that makes this painful in Rust is the lack of delegation. A hypothetical delegation syntax could be something like

impl MyArray {
    delegate call_to_whatever -> self.0; 
}

因此,当应该时,您使用 Deref / DerefMut ?我主张只有在实现智能指针时才有意义。

So when should you use Deref / DerefMut? I'd advocate that the only time it makes sense is when you are implementing a smart pointer.

实际上,我使用 Deref / DerefMut 表示。这是因为我信任自己,并且对我的意思有很好的了解。如果存在委托语法,我就不会。

Speaking practically, I do use Deref / DerefMut for newtypes that are not exposed publicly on projects where I am the sole or majority contributor. This is because I trust myself and have good knowledge of what I mean. If delegation syntax existed, I wouldn't.