Как использовать перегрузку параметров или дополнительные параметры в rust?
Я пытаюсь написать функцию печати для бинарного дерева, и вот что у меня есть до сих пор:
impl TreeNode {
fn print(&self) {
self.print(0);
}
fn print(&self, level: u8) {
for _i in range(0,level) {
print!("t");
}
match self.data {
Some(x) => println!("{}",x),
None => ()
};
match self.left {
Some(ref x) => x.print(level+1),
None => ()
};
match self.right {
Some(ref x) => x.print(level+1),
None => ()
};
}
}
Я получаю ошибку: дублирование определения значения print
. Поэтому мне было интересно, есть ли способ создавать функции с одинаковым именем, но разными аргументами. Альтернативно дополнительные параметры решат эту проблему, но я не думаю, что это возможно в данный момент (по крайней мере, я не смог найти его через поиск Google).
Итак, что это лучший способ, чтобы сделать это? Переименование вторая функция печати работает, но выглядит некрасиво и требует запоминания более одного имени функции, если я хочу (для этого примера) печатать, начиная с середины дерева.
1 ответ:
Rust не имеет перегрузки, поэтому невозможно иметь две функции или методы с одинаковым именем и с разными наборами параметров.
Однако иногда можно эмулировать перегрузку с помощью признаков. Этот подход, вероятно, не подходит для вашего случая использования, но вы можете увидеть, как это делается в стандартной библиотеке , гдеPath::new()
конструктор может быть вызван с чем-то, напоминающим вектор байтов:Path::new("/a/b/c/d") // argument is &str Path::new(b"/a/b/c/d") // argument is &[u8] Path::new(Path::new("/a/b/c/d")) // argument is another Path
Это делается через
BytesContainer
признак, иnew()
метод определяется следующим образом:fn new<T: BytesContainer>(bytes: T) -> Path { ... }
Тогда эта черта реализуется для всех типов, которые вы хотите:
impl<'a> BytesContainer for &'a str { ... } impl<'a> BytesContainer for &'a [u8] { ... } impl BytesContainer for Path { ... } // and more
Это напоминает перегрузку именно потому, что
new()
делает точно то же самое независимо от того, какой тип входных данных он предоставляет; это просто удобная вещь, которая делаетPath
конструктор более гибким. В конце концовnew()
просто преобразует свой аргумент в байтовый срез. Однако это не позволяет вам иметь совершенно разные функции с одним и тем же именем.