Error E0624 de Rust: method is private (método privado)
E0624 significa: el método que llamaste existe, pero se escribió sin pub, así que solo el código de dentro de su módulo puede llamarlo. El struct puede ser público, y el módulo también. Aun así, los métodos empiezan siendo privados, uno por uno. Es muy común justo después de mover un tipo a su propio módulo, y la solución suele ser añadir pub delante de fn. Esta página forma parte de la guía de errores del compilador.
El mensaje de error
Sección titulada «El mensaje de error»error[E0624]: associated function `new` is private --> src/main.rs:18:38 | 7 | fn new() -> Account { // sin `pub` | ------------------- private associated function defined here...18 | let mut account = bank::Account::new(); // ❌ función asociada privada | ^^^ private associated function
error[E0624]: method `add_interest` is private --> src/main.rs:19:13 |11 | fn add_interest(&mut self) { // sin `pub` | -------------------------- private method defined here...19 | account.add_interest(); // ❌ método privado | ^^^^^^^^^^^^ private method“Associated function new is private” quiere decir “la función asociada new es privada”, y “method add_interest is private”, “el método add_interest es privado”. defined here señala dónde está definido cada uno.
Este es el programa que lo produce:
mod bank { pub struct Account { balance: u64, }
impl Account { fn new() -> Account { // sin `pub` Account { balance: 0 } }
fn add_interest(&mut self) { // sin `pub` self.balance += self.balance / 100; } }}
fn main() { let mut account = bank::Account::new(); // ❌ función asociada privada account.add_interest(); // ❌ método privado}rustc usa aquí dos nombres. Un método recibe self (account.add_interest()). Una función asociada no tiene self y se llama con :: (Account::new()). La regla y la solución son las mismas para los dos.
Qué significa
Sección titulada «Qué significa»Cada error tiene dos flechas. La flecha ^^^ es tu llamada. La flecha --- muestra la línea fn a la que le falta el pub. Así que el mensaje te dice exactamente dónde añadirlo.
Estar dentro de impl Account no hace público un método, aunque Account sea pub. Piensa en un restaurante: la carta es pública, así que puedes pedir platos (los métodos pub). La cocina tiene sus propios pasos, como “picar cebolla”, que no puedes pedir directamente. Esos son los métodos privados.
Por qué Rust hace esto
Sección titulada «Por qué Rust hace esto»En Rust todo es privado por defecto, y los métodos no son una excepción (mira Módulos). La privacidad pertenece al módulo donde está escrito el bloque impl: cualquier código de mod bank puede llamar a add_interest, y el código de fuera no.
Esto deja que un tipo tenga pequeños métodos auxiliares que solo tienen sentido en el orden correcto. Imagina que add_interest debe ejecutarse una vez al mes, después de cobrar las comisiones. Si cualquiera pudiera llamarlo, alguien lo llamaría dos veces sin querer. Con métodos auxiliares privados y un método público que los ejecuta bien, ese error se vuelve imposible.
Además, te deja las manos libres. Los métodos privados se pueden renombrar, juntar o borrar cuando quieras, porque el compilador garantiza que ningún código de fuera los usa.
Cómo solucionarlo
Sección titulada «Cómo solucionarlo»Solución 1: Añade pub al método
Sección titulada «Solución 1: Añade pub al método»Elige esta cuando el método está pensado para llamarse desde fuera. Con new casi siempre es así: un constructor que nadie puede llamar no sirve de mucho.
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!("Saldo: {}", account.balance());}Salida:
Saldo: 1010Solución 2: Llama al método público pensado para ti
Sección titulada «Solución 2: Llama al método público pensado para ti»Elige esta cuando el método privado es un auxiliar, sobre todo en código que no escribiste tú. A menudo hay un método público que lo llama por ti, en el orden correcto y con las comprobaciones correctas. Aquí, dejar add_interest privado es el diseño correcto:
mod bank { pub struct Account { balance: u64, }
impl Account { pub fn new(opening: u64) -> Account { Account { balance: opening } }
// La entrada pública: una llamada hace todo el mes, en el orden correcto. pub fn close_month(&mut self) { self.charge_fee(); self.add_interest(); }
pub fn balance(&self) -> u64 { self.balance }
// Auxiliares privados: llamarlos solos, o dos veces, da resultados incorrectos. 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!("Después de un mes: {}", account.balance()); // account.add_interest(); // ❌ E0624: method `add_interest` is private}Salida:
Después de un mes: 1004Una buena regla: haz pub un método solo si llamarlo por sí solo, en cualquier momento no puede romper el struct. Si solo tiene sentido como un paso de algo más grande, déjalo privado y expón eso más grande.
Solución 3: Usa pub(crate) para “solo mi código”
Sección titulada «Solución 3: Usa pub(crate) para “solo mi código”»Elige esta cuando otros módulos de tu crate necesitan el método, pero la gente que usa tu biblioteca no debería verlo. pub(super) (solo el módulo padre) funciona igual; la página de E0603 tiene una tabla con todos los niveles.
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); }
// Solo para nuestro propio código (como los recibos), no para quien usa la biblioteca. pub(crate) fn total(&self) -> u32 { self.prices.iter().sum() } }}
mod receipt { pub fn print(cart: &crate::shop::Cart) { println!("Total: {}", cart.total()); }}
fn main() { let mut cart = shop::Cart::new(); cart.add(3); cart.add(5); receipt::print(&cart);}Salida:
Total: 8Un detalle: en un paquete con src/lib.rs y src/main.rs, hay dos crates. Un pub(crate) fn total en lib.rs es privado para main.rs:
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 hererustc señala la llamada en main.rs y, debajo, el método pub(crate) definido en lib.rs. Ahí, usa pub a secas. Mira Cargo y crates.
Solución 4: Mueve dentro del módulo el código que lo necesita
Sección titulada «Solución 4: Mueve dentro del módulo el código que lo necesita»Elige esta cuando el método de verdad debe seguir siendo privado, pero algún código lo necesita igualmente, como una auditoría o una prueba. El código del mismo módulo puede llamarlo, y también un módulo hijo: los módulos de dentro de bank pueden ver todo lo privado de bank.
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 } }
// Un módulo hijo puede usar todo lo privado de su padre. pub mod audit { pub fn check(account: &super::Account) -> &'static str { if account.is_suspicious() { "revisar, por favor" } else { "ok" } } }}
fn main() { let small = bank::Account::new(500); let big = bank::Account::new(50_000); println!("pequeña: {}", bank::audit::check(&small)); println!("grande: {}", bank::audit::check(&big));}Salida:
pequeña: okgrande: revisar, por favorLas pruebas unitarias funcionan igual. Un mod tests escrito dentro de bank (o al final de src/bank.rs) es un módulo hijo, así que puede llamar a métodos privados. Mira Pruebas:
#[cfg(test)]mod tests { use super::*;
#[test] fn not_suspicious_when_small() { let account = Account::new(500); assert!(!account.is_suspicious()); // privado, pero aquí está permitido }}Dónde lo verás normalmente
Sección titulada «Dónde lo verás normalmente»Un bloque impl en otro módulo. La privacidad pertenece al módulo donde está escrito el impl, no al struct. Si Order vive en mod model pero escribes impl Order { fn with_tax(&self) ... } dentro de mod pricing, entonces main recibe method `with_tax` is private, señalando a mod pricing. Solución: pub fn with_tax, o pub(crate).
Usar un método como valor de función. accounts.iter().map(bank::Account::audit) es la misma llamada escrita de otra forma, así que da el mismo E0624. La solución es la misma.
Métodos de traits. Nunca escribes pub en los métodos de dentro de impl SomeTrait for Type. Son tan públicos como el trait, y añadir pub es un error: error[E0449]: visibility qualifiers are not permitted here (aquí no se permiten modificadores de visibilidad). Si parece que falta un método de un trait, te saldrá E0599, y la solución es importar el trait con use.
Un método privado de un crate. Encontraste el método perfecto en el código fuente de un crate en GitHub, pero no es pub. No puedes llamarlo, y sus autores pueden cambiarlo en cualquier versión. Busca un método público que haga lo mismo en la página del crate en docs.rs; allí solo aparecen los elementos pub.
Errores relacionados
Sección titulada «Errores relacionados»- E0603:
function `x` is private. La misma idea, pero para funciones sueltas, structs y módulos. - E0616:
field `x` of struct `Y` is private, al leer o escribir un campo. - E0451: un campo privado al construir un struct con
Y { ... }. Normalmente se arregla con unpub fn new. - E0599:
no method named `x` found. El método no existe para ese tipo, o su trait no está en el ámbito (scope). - Todos los errores del compilador: la lista completa de páginas de errores.
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. pub struct Timer tiene impl Timer { fn start() -> Timer { ... } } dentro de mod clock. ¿Qué pasa cuando main llama a clock::Timer::start()?
2. ¿Qué código puede llamar a un método privado definido en mod bank?
3. Un add_interest privado solo debe ejecutarse una vez al mes, después de las comisiones. ¿Cuál es la mejor solución para E0624?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- E0624 — Rust error codes index (en inglés): la explicación oficial, con un ejemplo mínimo.
- Method Syntax — El libro de Rust (en inglés): métodos, funciones asociadas y bloques
impl. También existe una traducción al español de la comunidad del libro. - Paths for Referring to an Item in the Module Tree — El libro de Rust (en inglés): cómo exponer elementos con
pub, paso a paso. - Testing Private Functions — El libro de Rust (en inglés): por qué las pruebas unitarias pueden llamar a código privado.
- Visibility and privacy — The Rust Reference (en inglés): las reglas exactas, incluidos
pub(crate),pub(super)ypub(in path).