Rust-Fehler E0615: attempted to take value of method (Methode ohne Klammern)
E0615 bedeutet: Du hast value.something ohne Klammern geschrieben, aber something ist eine Methode und kein Feld. In Rust läuft eine Methode nur, wenn du sie mit () aufrufst – auch dann, wenn sie keine Argumente braucht. Dieser Fehler ist sehr häufig, wenn du von C#, JavaScript oder Python kommst. Dort sehen .Count, .length oder eine Property wie ganz normale Felder aus. Die Lösung ist fast immer zwei Zeichen lang. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0615]: attempted to take value of method `len` on type `String` --> src/main.rs:3:46 |3 | println!("{} has {} letters", name, name.len); // ❌ `len` ist eine Methode | ^^^ method, not a field |help: use parentheses to call the method |3 | println!("{} has {} letters", name, name.len()); // ❌ `len` ist eine Methode | ++„Attempted to take value of method“ heißt so viel wie „Versuch, den Wert einer Methode zu nehmen“. Das help sagt: „Benutze Klammern, um die Methode aufzurufen.“
Dieses Programm erzeugt den Fehler:
fn main() { let name = String::from("Ferris"); println!("{} has {} letters", name, name.len); // ❌ `len` ist eine Methode}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Lies die Überschrift von hinten: on type String ist der Typ, den Rust sich angesehen hat, und method len ist das, was es dort gefunden hat. Rust hat len also gefunden. Es ist nur kein Wert, den du wie ein Feld lesen kannst. Es ist ein Stück Code, das erst laufen muss.
Genau das sagen die Markierung method, not a field (Methode, kein Feld) und die ++ unter () im help: Setz die Klammern, und du bist fertig.
Stell dir einen Getränkeautomaten vor. Ein Feld ist ein Schild, das auf den Automaten gedruckt ist („Automat Nr. 12“): Du liest es einfach ab. Eine Methode ist ein Knopf („Wechselgeld anzeigen“): Es passiert nichts, bis du ihn drückst. name.len zeigt auf den Knopf. name.len() drückt ihn.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Rust trennt Felder und Methoden streng. Ein Feld sind Daten, die im Struct gespeichert sind. Eine Methode ist eine Funktion in einem impl-Block, die self nimmt. Ein Feld liest du mit value.field, eine Methode rufst du mit value.method() auf. Siehe Verhalten mit Methoden hinzufügen.
Viele Sprachen verwischen diese Grenze mit Properties: list.Count in C# oder text.length in JavaScript sehen wie Felder aus, führen aber im Hintergrund Code aus. Rust hat absichtlich keine Properties. Siehst du (), weißt du: Hier läuft Code, und das kann Zeit kosten. Siehst du keine Klammern, ist es einfaches Lesen von gespeicherten Daten. Nichts ist versteckt.
Ein Struct kann sogar ein Feld und eine Methode mit demselben Namen haben, etwa ein privates Feld balance und eine öffentliche Methode balance(). Das geht nur, weil Rust nie rät, was du gemeint hast: ohne Klammern das Feld, mit Klammern die Methode.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: Die Klammern setzen
Abschnitt betitelt „Lösung 1: Die Klammern setzen“Nimm diese Lösung fast immer. Folge der help:-Zeile und ruf die Methode auf. Das funktioniert für deine eigenen Methoden (wie total bei einem Warenkorb) genauso wie für Standardmethoden wie len, is_empty, trim und count:
struct Item { price: u32, // in Cent qty: u32,}
struct Cart { items: Vec<Item>,}
impl Cart { fn total(&self) -> u32 { self.items.iter().map(|i| i.price * i.qty).sum() }}
fn main() { let name = String::from("Ferris"); println!("{} hat {} Buchstaben", name, name.len()); // ✅ aufgerufen
let cart = Cart { items: vec![Item { price: 250, qty: 2 }, Item { price: 100, qty: 1 }], }; if !cart.items.is_empty() { println!("Summe: {} Cent", cart.total()); // ✅ aufgerufen }}Ausgabe:
Ferris hat 6 BuchstabenSumme: 600 CentBraucht die Methode Argumente, zeigt rustc mit einem Platzhalter _, wo sie hingehören. Bei s.contains lautet das help s.contains(_): Setz ein, wonach du suchst, zum Beispiel s.contains("world"). Bist du nicht sicher, was eine Methode braucht, sagt dir der nächste Fehler von rustc (E0061), wie viele Argumente sie nimmt.
Lösung 2: Die Methode als Funktion übergeben, nicht value.method
Abschnitt betitelt „Lösung 2: Die Methode als Funktion übergeben, nicht value.method“Nimm diese Lösung, wenn du die Methode gar nicht sofort aufrufen wolltest, sondern sie an etwas anderes weitergeben willst, etwa an .map() oder sort_by_key. Auch .map(words[0].len) ergibt E0615. Du hast zwei gute Möglichkeiten: ein kurzes Closure, das die Methode aufruft, oder den vollen Pfad der Methode, String::len, der wie ein Funktionsname funktioniert:
fn main() { let words = vec![String::from("crab"), String::from("ferris"), String::from("rust")];
// ein Closure, das die Methode für jedes Element aufruft let lengths: Vec<usize> = words.iter().map(|w| w.len()).collect(); println!("{:?}", lengths);
// der Pfad der Methode funktioniert wie ein Funktionsname let same: Vec<usize> = words.iter().map(String::len).collect(); println!("{:?}", same);
let mut sorted = words.clone(); sorted.sort_by_key(|w| w.len()); println!("{:?}", sorted);}Ausgabe:
[4, 6, 4][4, 6, 4]["crab", "rust", "ferris"]Die Wörter bleiben hier auf Englisch, weil die Ausgabe ihre Länge zeigt. String::len funktioniert, weil iter() dir &String-Elemente gibt und String::len ein &String nimmt. Passen die Typen nicht genau zusammen, ist das Closure |w| w.len() die einfache Wahl, die immer klappt.
Lösung 3: Ein Feld daraus machen, wenn es wirklich gespeicherte Daten sind
Abschnitt betitelt „Lösung 3: Ein Feld daraus machen, wenn es wirklich gespeicherte Daten sind“Nimm diese Lösung, wenn der Fehler in deinem eigenen Struct steckt und du merkst, dass der Wert einfach gespeichert werden sollte. Das ist eine Designfrage: Feld oder Methode?
- Mach ein Feld daraus, wenn der Wert einmal festgelegt wird und von nichts anderem abhängt: eine
id, einname, ein Datumcreated_at. - Mach eine Methode daraus, wenn der Wert aus anderen Daten berechnet wird: eine
totalaus den Artikeln, eineareaaus Breite und Höhe, einelenaus dem Inhalt.
Ein gespeichertes Feld total wäre veraltet, sobald jemand einen Artikel hinzufügt und vergisst, es zu aktualisieren. Eine Methode total() wird jedes Mal neu berechnet, sie kann also nie falsch sein. Hier ist id ein Feld und total eine Methode, und du siehst, dass die Methode stimmt, auch wenn sich die Bestellung ändert:
mod shop { pub struct Order { pub id: u32, // gespeichert: einmal gesetzt, gelesen mit order.id prices: Vec<u32>, // privat: wird nur über Methoden geändert }
impl Order { pub fn new(id: u32) -> Self { Order { id, prices: Vec::new() } }
pub fn add(&mut self, price: u32) { self.prices.push(price); }
// berechnet: passt immer zu den Preisen, kann nicht veralten pub fn total(&self) -> u32 { self.prices.iter().sum() }
pub fn item_count(&self) -> usize { self.prices.len() } }}
use shop::Order;
fn main() { let mut order = Order::new(17); order.add(250); order.add(100); println!("Bestellung {}: {} Artikel, {} Cent", order.id, order.item_count(), order.total());
order.add(50); println!("Bestellung {}: {} Artikel, {} Cent", order.id, order.item_count(), order.total());}Ausgabe:
Bestellung 17: 2 Artikel, 350 CentBestellung 17: 3 Artikel, 400 CentEs gibt einen Mittelweg, den du in vielen Bibliotheken siehst: ein privates Feld plus eine öffentliche Methode mit demselben Namen (ein „Getter“). Anderer Code kann den Wert mit acc.balance() lesen, ihn aber nicht direkt ändern. Schreibst du acc.balance von außerhalb des Moduls, bekommst du einen etwas anderen Fehler: E0616 „field balance of struct Account is private“ (das Feld ist privat), mit dem Hinweis a method `balance` also exists, call it with parentheses (es gibt auch eine Methode balance, ruf sie mit Klammern auf). Die Lösung ist dieselbe: () ergänzen. Siehe Alles ist standardmäßig privat.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Gewohnheiten aus anderen Sprachen. name.len, list.is_empty, text.trim, words.iter().count ergeben alle E0615. Jede davon ist in Rust eine Methode, also braucht jede (). Lösung: name.len(), list.is_empty() und so weiter. Siehe Nützliche String-Methoden.
len bei einem Vec. scores.len ist die eine Ausnahme: Du bekommst E0616, „field len of struct Vec is private“ (das Feld len ist privat), weil Vec wirklich ein verstecktes Feld namens len hat. rustc ergänzt trotzdem help: a method `len` also exists, call it with parentheses. Lösung: scores.len(). (scores.is_empty ergibt das normale E0615.) Siehe Vektoren.
Eine Methode, die etwas ändert. Auch counter.increment; allein in einer Zeile ergibt E0615, obwohl du gar keinen Wert haben wolltest. Ohne () läuft nichts. Lösung: counter.increment();.
Andersherum: ein Feld wie eine Methode aufrufen. Ist name ein Feld, ergibt user.name() den Fehler E0599 mit der Markierung field, not a method (Feld, keine Methode) und help: remove the arguments (entferne die Argumente). Lösung: user.name. Und wenn das Feld ein Closure enthält, etwa on_click: Box<dyn Fn() -> String>, sagt rustc surround the field access with parentheses (setz den Feldzugriff in Klammern): Schreib (button.on_click)(), um es aufzurufen.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0609: no field
xon typeT: Der Name nach dem Punkt ist weder ein Feld noch eine Methode dieses Typs. Meistens ein Tippfehler oder eineOption, die du erst auspacken musst. - E0599: no method named x found: die umgekehrte Richtung,
user.name(), wennnameein Feld ist, oder eine Methode, die es nicht gibt. - E0616: field is private:
scores.lenbei einemVec, oder ein privates Feld mit einem öffentlichen Getter gleichen Namens. Ruf stattdessen die Methode auf. - E0061: wrong number of arguments: Du hast die
()ergänzt, aber die Methode braucht Argumente. - E0610: primitive type doesn’t have fields:
.somethingan einer Zahl, einembooloder einemchar. - Alle Compilerfehler einfach erklärt
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Du bekommst „attempted to take value of method is_empty on type String“. Was ist die Lösung?
2. Was sollte meistens eine Methode statt eines gespeicherten Felds sein?
3. Du willst die Länge jedes Worts: words.iter().map(???). Was funktioniert?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0615 – Rust error codes index (auf Englisch): die offizielle Erklärung dieses Fehlers.
- Methoden – Das Rust-Buch: wie Methoden definiert und aufgerufen werden, und Getter, die so heißen wie ein Feld.
- Strukturen definieren und instanziieren – Das Rust-Buch: Felder, und wie du sie mit der Punkt-Schreibweise liest.
- Method call expressions – The Rust Reference (auf Englisch): die genauen Regeln für
value.method(). - Methods – Rust by Example (auf Englisch): kurze, ausführbare Beispiele für Methoden und assoziierte Funktionen.