Zum Inhalt springen

Rust-Fehler E0624: method is private (private Methode)

E0624 bedeutet: Die Methode, die du aufrufst, existiert – aber sie wurde ohne pub geschrieben, also darf nur Code innerhalb ihres Moduls sie aufrufen. Das Struct darf öffentlich sein, das Modul auch. Methoden sind trotzdem zuerst privat, jede einzeln. Der Fehler taucht besonders oft auf, direkt nachdem du einen Typ in ein eigenes Modul verschoben hast. Meistens behebst du ihn, indem du pub vor fn schreibst. Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.

error[E0624]: associated function `new` is private
--> src/main.rs:18:38
|
7 | fn new() -> Account { // kein `pub`
| ------------------- private associated function defined here
...
18 | let mut account = bank::Account::new(); // ❌ private assoziierte Funktion
| ^^^ private associated function
error[E0624]: method `add_interest` is private
--> src/main.rs:19:13
|
11 | fn add_interest(&mut self) { // kein `pub`
| -------------------------- private method defined here
...
19 | account.add_interest(); // ❌ private Methode
| ^^^^^^^^^^^^ private method

Auf Deutsch heißt das: „Die assoziierte Funktion new ist privat“ und „Die Methode add_interest ist privat“. Dieses Programm erzeugt die Meldungen:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
fn new() -> Account { // kein `pub`
Account { balance: 0 }
}
fn add_interest(&mut self) { // kein `pub`
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(); // ❌ private assoziierte Funktion
account.add_interest(); // ❌ private Methode
}

rustc benutzt hier zwei Namen. Eine Methode (method) nimmt self (account.add_interest()). Eine assoziierte Funktion (associated function) hat kein self und wird mit :: aufgerufen (Account::new()). Regel und Lösung sind für beide gleich.

Jeder Fehler hat zwei Markierungen. Die ^^^-Markierung ist dein Aufruf. Die ----Markierung zeigt die fn-Zeile, der das pub fehlt. Die Meldung sagt dir also genau, wo du es ergänzen musst.

Dass eine Methode in impl Account steht, macht sie nicht öffentlich – auch dann nicht, wenn Account pub ist. Denk an ein Restaurant: Die Speisekarte ist öffentlich, du kannst also Gerichte bestellen (pub-Methoden). Die Küche hat ihre eigenen Arbeitsschritte, etwa „Zwiebeln schneiden“. Die kannst du nicht direkt bestellen. Das sind die privaten Methoden.

In Rust ist alles standardmäßig privat, und Methoden sind keine Ausnahme (siehe Module). Die Sichtbarkeit gehört zu dem Modul, in dem der impl-Block steht: Jeder Code in mod bank darf add_interest aufrufen, Code von außerhalb nicht.

So kann ein Typ kleine Hilfsmethoden haben, die nur in der richtigen Reihenfolge Sinn ergeben. Stell dir vor, add_interest soll einmal im Monat laufen, nachdem die Gebühren abgebucht sind. Dürfte jeder sie aufrufen, würde irgendwer sie aus Versehen zweimal aufrufen. Private Hilfsmethoden plus eine öffentliche Methode, die sie korrekt ausführt, machen diesen Fehler unmöglich.

Außerdem bleibst du flexibel. Private Methoden kannst du jederzeit umbenennen, zusammenlegen oder löschen, denn der Compiler garantiert, dass kein Code von außen sie benutzt.

Nimm diese Lösung, wenn die Methode von außen aufgerufen werden soll. Bei new ist das fast immer so: Ein Konstruktor, den niemand aufrufen kann, nützt wenig.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
pub fn add_interest(&mut self) {
self.balance += self.balance / 100; // 1 %
}
pub fn balance(&self) -> u64 {
self.balance
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.add_interest();
println!("Kontostand: {}", account.balance());
}

Ausgabe:

Kontostand: 1010
▶ Selbst ausprobieren

Lösung 2: Die öffentliche Methode aufrufen, die für dich gedacht ist

Abschnitt betitelt „Lösung 2: Die öffentliche Methode aufrufen, die für dich gedacht ist“

Nimm diese Lösung, wenn die private Methode eine Hilfsmethode ist, besonders in Code, den du nicht selbst geschrieben hast. Oft gibt es eine öffentliche Methode, die sie für dich aufruft – in der richtigen Reihenfolge und mit den richtigen Prüfungen. Hier ist es genau das richtige Design, add_interest privat zu lassen:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
// Der öffentliche Weg: Ein Aufruf erledigt den ganzen Monat, in der richtigen Reihenfolge.
pub fn close_month(&mut self) {
self.charge_fee();
self.add_interest();
}
pub fn balance(&self) -> u64 {
self.balance
}
// Private Hilfsmethoden: Einzeln oder doppelt aufgerufen liefern sie falsche Ergebnisse.
fn charge_fee(&mut self) {
self.balance = self.balance.saturating_sub(5);
}
fn add_interest(&mut self) {
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.close_month();
println!("Nach einem Monat: {}", account.balance());
// account.add_interest(); // ❌ E0624: method `add_interest` is private
}

Ausgabe:

Nach einem Monat: 1004
▶ Selbst ausprobieren

Eine gute Faustregel: Mach eine Methode nur dann pub, wenn sie das Struct allein und zu jedem Zeitpunkt aufgerufen nicht kaputtmachen kann. Ergibt sie nur als ein Schritt von etwas Größerem Sinn, lass sie privat und mach das Größere öffentlich.

Lösung 3: pub(crate) für „nur mein eigener Code“

Abschnitt betitelt „Lösung 3: pub(crate) für „nur mein eigener Code““

Nimm diese Lösung, wenn andere Module deines Crates die Methode brauchen, Benutzer deiner Library aber nicht. pub(super) (nur das übergeordnete Modul) funktioniert genauso. Auf der Seite zu E0603 findest du eine Tabelle mit allen Stufen.

mod shop {
pub struct Cart {
prices: Vec<u32>,
}
impl Cart {
pub fn new() -> Cart {
Cart { prices: Vec::new() }
}
pub fn add(&mut self, price: u32) {
self.prices.push(price);
}
// Nur für unseren eigenen Code (etwa Kassenbons), nicht für Library-Benutzer.
pub(crate) fn total(&self) -> u32 {
self.prices.iter().sum()
}
}
}
mod receipt {
pub fn print(cart: &crate::shop::Cart) {
println!("Summe: {}", cart.total());
}
}
fn main() {
let mut cart = shop::Cart::new();
cart.add(3);
cart.add(5);
receipt::print(&cart);
}

Ausgabe:

Summe: 8
▶ Selbst ausprobieren

Ein Haken: In einem Paket mit src/lib.rs und src/main.rs sind das zwei Crates. Ein pub(crate) fn total in lib.rs ist für main.rs privat:

error[E0624]: method `total` is private
--> src/main.rs:3:25
|
3 | println!("{}", cart.total());
| ^^^^^ private method
|
::: src/lib.rs:10:5
|
10 | pub(crate) fn total(&self) -> u32 {
| --------------------------------- private method defined here

Die Meldung zeigt deinen Aufruf in main.rs und darunter die Definition in lib.rs. Nimm dort einfach pub. Siehe Cargo und Crates.

Lösung 4: Den Code, der sie braucht, ins Modul verschieben

Abschnitt betitelt „Lösung 4: Den Code, der sie braucht, ins Modul verschieben“

Nimm diese Lösung, wenn die Methode wirklich privat bleiben soll, ein bestimmter Code sie aber trotzdem braucht, etwa eine Prüfung oder ein Test. Code im selben Modul darf sie aufrufen, und ein Kind-Modul auch: Module innerhalb von bank sehen alles, was in bank privat ist.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
fn is_suspicious(&self) -> bool {
self.balance > 10_000
}
}
// Ein Kind-Modul darf alles Private seines Eltern-Moduls benutzen.
pub mod audit {
pub fn check(account: &super::Account) -> &'static str {
if account.is_suspicious() { "bitte prüfen" } else { "ok" }
}
}
}
fn main() {
let small = bank::Account::new(500);
let big = bank::Account::new(50_000);
println!("klein: {}", bank::audit::check(&small));
println!("groß: {}", bank::audit::check(&big));
}

Ausgabe:

klein: ok
groß: bitte prüfen
▶ Selbst ausprobieren

Mit Unit-Tests ist es genauso. Ein mod tests innerhalb von bank (oder am Ende von src/bank.rs) ist ein Kind-Modul und darf deshalb private Methoden aufrufen. Siehe Testen:

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn not_suspicious_when_small() {
let account = Account::new(500);
assert!(!account.is_suspicious()); // privat, aber hier erlaubt
}
}

Ein impl-Block in einem anderen Modul. Die Sichtbarkeit gehört zu dem Modul, in dem der impl-Block steht, nicht zum Struct. Liegt Order in mod model, du schreibst aber impl Order { fn with_tax(&self) ... } in mod pricing, dann bekommt main method `with_tax` is private, mit Verweis auf mod pricing. Lösung: pub fn with_tax oder pub(crate).

Eine Methode als Funktionswert benutzen. accounts.iter().map(bank::Account::audit) ist derselbe Aufruf, nur anders geschrieben. Er liefert also dasselbe E0624. Die Lösung ist dieselbe.

Trait-Methoden. An Methoden in impl SomeTrait for Type schreibst du nie pub. Sie sind so öffentlich wie der Trait, und ein zusätzliches pub ist ein Fehler: error[E0449]: visibility qualifiers are not permitted here („Sichtbarkeitsangaben sind hier nicht erlaubt“). Scheint eine Trait-Methode zu fehlen, bekommst du stattdessen E0599. Dann hilft es, den Trait mit use einzubinden.

Die private Methode eines Crates. Du hast im Quellcode eines Crates auf GitHub die perfekte Methode gefunden, aber sie ist nicht pub. Aufrufen kannst du sie nicht, und ihre Autoren können sie in jedem Release ändern. Such auf der Seite des Crates bei docs.rs nach einer öffentlichen Methode, die die Aufgabe erledigt. Dort erscheinen nur pub-Elemente.

  • E0603: function `x` is private. Dieselbe Idee für freie Funktionen, Structs und Module.
  • E0616: field `x` of struct `Y` is private, wenn du ein Feld liest oder schreibst.
  • E0451: ein privates Feld beim Bauen eines Structs mit Y { ... }. Meistens hilft ein pub fn new.
  • E0599: no method named `x` found. Die Methode gibt es für diesen Typ nicht, oder ihr Trait ist nicht im Gültigkeitsbereich (Scope).
  • Alle Compilerfehler: die vollständige Liste der Fehlerseiten.

Kurzer Check

1. pub struct Timer hat impl Timer { fn start() -> Timer { ... } } in mod clock. Was passiert, wenn main clock::Timer::start() aufruft?

2. Welcher Code darf eine private Methode aufrufen, die in mod bank definiert ist?

3. Ein privates add_interest darf nur einmal im Monat laufen, nach den Gebühren. Was ist die beste Lösung für E0624?

Punkte: 0 / 3