I see some structures in Rust use a default
for there construction, while I see others use new
.1 Is there any semantic difference between the use of new
vs default
, or is everything convention? And if it is convention, is there any official standards on what that convention/style is?
I do see that there is a Default
trait, with a macro that creates a default default
function for simple structs, where as I do not see a similar thing for new
. This makes me guess that new
is meant for the actual constructor, while default
is mostly just meant when using the struct in other data structures. But I cannot find anything that states that is correct or incorrect.2
Finally, does it matter if the constructor has (possibly optional) parameters for building the structure? It looks like default
works best if it takes no arguments, but I'm not confident of this. For simple constructors say a point class:
#[defive(Default)]
pub struct Point {
pub x: u32,
pub y: u32,
pub z: u32
}
Users could construct it by using:
Point {x: 42, ..Default::default()}
But that only works if all of the fields a user might change are public.
In conclusion, when is it appropriate to use new
vs default
when constructing structures in Rust, both when a constructor takes no arguments, or possibly optional arguments?
1 I also see a few others just use the name of the structure, but I think that's deprecated?
2 It might be possible that it is neither correct nor incorrect, making it subjective and not really appropriate on stack overflow. Because of this ambiguity I think that even if it is subjective, it is objective to state that its subjective, making it again appropriate for SO.
Do not think of the question as new()
vs. default()
, but rather new()
vs. Default
. It's not that Default
provides a convenient default()
, it's that default()
is the function name for Default
— it would be unidiomatic to write a fn default()
that is not an implementation of Default
.
If your type has a reasonable way to construct it without any data, an “empty” value of its type, then it should:
Implement Default
. This way, other types containing yours can benefit from it in their own Default
, and in general you get all the benefits of implementing common traits.
Provide a new()
with no parameters, if there isn't already a more natural new()
that takes parameters.
(For example, Box
, Cell
, and other containers of a single value will typically have a new()
with one parameter, but also implement Default
by calling the inner type's Default::default()
. In that case, new()
and default()
are not the same.)
If possible, make the new()
function (whether or not it has parameters) a const fn
. This allows callers to create values of your type at compile time, which is useful for things like initializing static
variables and const
s with initially-empty or always-empty values.
(Trait implementations cannot yet have const fn
s, so this is a benefit of providing a function even when you also implement Default
.)