Well, to remedy this, functions are named according to what they do, but people across the ecosystem are pretty consistent about it.
For example, if we're accessing some property mutably (I know this isn't an "overloadable" example, but bear with me), then we append a _mut
suffix. Otherwise it's just the variable name:
struct Foo {
bar: String
}
impl Foo {
fn bar(&self) -> &str {
&self.bar
}
fn bar_mut(&mut self) -> &mut String {
&mut self.bar
}
}
Or, if you're getting to the point where you could have any number of parameters, and it becomes unwieldy to try and model every case (this is when the number of arguments usually exceeds 2), then we use a different pattern. Either the builder pattern (I believe it's called the factory pattern in other languages):
struct WindowBuilder {
title: String,
size: WindowSize,
something_else: ...
}
impl WindowBuilder {
pub fn new() -> Self {
Self {
title: String::new(),
size: WindowSize::default(),
something_else: Default::default(),
}
}
pub fn build(self) -> Window {
Window::from(self)
}
pub fn title(&mut self, title: impl Into<String>) -> &mut Self {
self.title = title;
self
}
// Other attributes
}
// Usage
let my_window = WindowBuilder::new()
.title("my cool window")
.size(200, 200)
.something_else(...)
.build();
Or, you could use different patterns out there, such as the init struct pattern:
struct WindowBuilder {
title: String,
size: WindowSize,
something_else: ...
}
impl Default for WindowBuilder {
fn default() -> Self {
Self {
title: String::new(),
size: WindowSize::default(),
something_else: Default::default(),
}
}
}
impl WindowBuilder {
pub fn init(self) -> Window {
Window::from(self)
}
}
// Usage:
let my_window = WindowBuilder {
title: "my awesome window".into(),
..Default::default()
}.init();