2014-07-24 12 views
7

Ich versuche, eine Druckfunktion für einen binären Baum zu schreiben und hier ist das, was ich bisher:Wie verwende ich Parameter Überladung oder optionale Parameter in Rost?

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 =>() 
     }; 
    } 
} 

ich die Störung erhalte: doppelte Definition von Wert print. Also habe ich mich gefragt, ob es eine Möglichkeit gibt, Funktionen mit demselben Namen aber unterschiedlichen Argumenten zu erstellen. Alternativ könnten optionale Parameter dieses Problem lösen, aber ich glaube nicht, dass dies im Moment möglich ist (zumindest konnte ich es nicht über eine Google-Suche finden).

Also, was ist der beste Weg, dies zu tun? Das Umbenennen der zweiten Druckfunktion funktioniert, sieht aber hässlich aus und erfordert, dass Sie sich mehr als einen Funktionsnamen merken, wenn ich (in diesem Beispiel) ab der Mitte des Baums drucken möchte.

Antwort

4

Rust haben nicht zu überlasten, so ist es unmöglich, zwei Funktionen oder Methoden mit dem gleichen Namen hat und mit unterschiedlichen Parametern.

Es ist jedoch manchmal möglich, Überladung mit Merkmalen zu emulieren. Dieser Ansatz ist für Ihren Anwendungsfall wahrscheinlich ungeeignet, aber man kann sehen, wie es in the standard library geschehen ist, wo Path::new() Konstruktor kann mit so etwas wie einem Vektor von Bytes aufgerufen werden:

Path::new("https://stackoverflow.com/a/b/c/d") // argument is &str 
Path::new(b"https://stackoverflow.com/a/b/c/d") // argument is &[u8] 
Path::new(Path::new("https://stackoverflow.com/a/b/c/d")) // argument is another Path 

Die über BytesContainer Merkmal gemacht wird, und new() Verfahren wird wie folgt definiert:

fn new<T: BytesContainer>(bytes: T) -> Path { ... } 

Dann ist dieses Merkmal für alle Arten implementiert Sie wollen:

impl<'a> BytesContainer for &'a str { ... } 
impl<'a> BytesContainer for &'a [u8] { ... } 
impl BytesContainer for Path { ... } 
// and more 

Das Überladen ähnelt genau, weil new() genau dasselbe tut, unabhängig davon, welche Art von Eingang es ist; es ist nur eine praktische Sache, die Path Konstruktor flexibler macht. Am Ende wandelt new() sein Argument in ein Byte-Slice um. Dies ermöglicht jedoch nicht, dass Sie völlig unterschiedliche Funktionen mit demselben Namen haben.

+2

Das macht mich traurig. Also, zurück zu meinem Beispiel, wäre das Beste, zu tun, die zweite Funktion etwas wie "print_at_level" zu nennen und es einfach dabei belassen? – user439299

+1

@ user439299, ja, genau. –