为新类型实现 Deref 是否被认为是一种不好的做法? [英] Is it considered a bad practice to implement Deref for newtypes?

查看:26
本文介绍了为新类型实现 Deref 是否被认为是一种不好的做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常使用 newtype 模式,但我厌倦了编写 my_type.0.call_to_whatever(...).我很想实现 Deref 特性,因为它允许编写更简单的代码,因为在某些情况下我可以像使用底层类型一样使用我的 newtype,eg:

I often use the newtype pattern, but I am tired of writing my_type.0.call_to_whatever(...). I am tempted to implement the Deref trait because it permits writing simpler code since I can use my newtype as if it were the underlying type in some situations, e.g.:

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
}

这是好还是坏的做法?为什么?有什么缺点?

Is this a good or bad practice? Why? What can be the downsides?

推荐答案

关于DerefDerefMut 的规则是专门为适应智能指针而设计的.因此,Deref 应该只为智能指针实现以避免混淆.

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


我认为这是一种不好的做法.

因为在某些情况下我可以将我的 newtype 当作底层类型使用

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-ahas-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(...)

与其他语言一样,我相信正确的解决方案是组合而不是继承.如果需要转接呼叫,请在 newtype 上创建一个方法:

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; 
}

在等待一流的委托时,我们可以使用像 delegate大使 帮助填补一些空白.

While waiting for first-class delegation, we can use crates like delegate or ambassador to help fill in some of the gaps.

那么什么时候应该使用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.

这篇关于为新类型实现 Deref 是否被认为是一种不好的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆