更新时间: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.