Files
JR-priprava-na-skusku/priprava/rust_priprava11.md
2026-03-05 00:35:59 +01:00

7.7 KiB

clap → match → volanie metód — kde robíš chybu

Tvoj problém nie je clap. Clap máš dobre. Tvoj problém je toto:

Sc::DajKnihuIsbn { cesta, isbn } => {
    Kniznica::daj_knihu_podla_isbn(isbn);  // ZLE
}

Tri chyby na jednom riadku:

  1. Nikde si nenačítal knižnicu zo súboru
  2. Voláš metódu ako statickú (Kniznica::) namiesto na inštancii (kniznica.)
  3. Ignoruješ návratovú hodnotu

Pravidlo 1: Najprv načítaj, potom volaj

Metódy ako daj_knihu_podla_isbn&self metódy — potrebujú inštanciu. Tú musíš najprv vytvoriť z JSON súboru.

// ZLE — Kniznica neexistuje, voláš na type
Kniznica::daj_knihu_podla_isbn(isbn);

// DOBRE — najprv načítaj, potom volaj na inštancii
let kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
kniznica.daj_knihu_podla_isbn(&isbn);

Pravidlo 2: Statické vs inštančné metódy

Pozri sa na signatúru metódy. To ti povie ako ju volať.

// STATICKÁ metóda — nemá self, volaj cez Typ::
fn nacitaj_zo_suboru(cesta: &PathBuf) -> Option<Kniznica>
// Volanie:
let kniznica = Kniznica::nacitaj_zo_suboru(&cesta);

// &self metóda — len čítanie, volaj cez instancia.
fn daj_knihu_podla_isbn(&self, isbn: &str) -> Option<&Kniha>
// Volanie:
let vysledok = kniznica.daj_knihu_podla_isbn(&isbn);

// &mut self metóda — mení dáta, volaj cez mut instancia.
fn pridaj_knihu(&mut self, kniha: Kniha) -> Result<(), ()>
// Volanie:
let mut kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
let vysledok = kniznica.pridaj_knihu(kniha);

Zhrnutie:

Signatúra Čo potrebuješ Volanie
fn nieco(cesta: &PathBuf) — bez self nič Kniznica::nieco(&cesta)
fn nieco(&self, ...) let kniznica = ... kniznica.nieco(...)
fn nieco(&mut self, ...) let mut kniznica = ... kniznica.nieco(...)

Pravidlo 3: Spracuj návratovú hodnotu

Každá metóda niečo vracia. Musíš s tým niečo urobiť.

// Option<&Kniha> — buď existuje, alebo nie
match kniznica.daj_knihu_podla_isbn(&isbn) {
    Some(kniha) => println!("{}", kniha),
    None => println!("Kniha nenájdená"),
}

// Vec<&Kniha> — môže byť prázdny
let knihy = kniznica.daj_knihy_autora(&autor);
if knihy.is_empty() {
    println!("Žiadne knihy");
} else {
    for kniha in &knihy {
        println!("{}", kniha);
    }
}

// Result<Kniha, ()> — podarilo sa alebo nie
match kniznica.odstran_knihu(&isbn) {
    Ok(kniha) => println!("Odstránená: {}", kniha),
    Err(()) => println!("Kniha nenájdená"),
}

Pravidlo 4: Ak meníš dáta, ulož na konci

// Čítacie metódy (&self) — NEUKLADAJ
Sc::DajKnihuIsbn { cesta, isbn } => {
    let kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
    // daj_knihu_podla_isbn je &self — len číta
    match kniznica.daj_knihu_podla_isbn(&isbn) {
        Some(kniha) => println!("{}", kniha),
        None => println!("Nenájdená"),
    }
    // ŽIADNE uloženie — nič sa nezmenilo
}

// Meniace metódy (&mut self) — ULOŽ!
Sc::OdstranKnihu { cesta, isbn } => {
    let mut kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
    // odstran_knihu je &mut self — mení dáta
    match kniznica.odstran_knihu(&isbn) {
        Ok(kniha) => {
            println!("Odstránená: {}", kniha);
            kniznica.uloz_do_suboru(&cesta);  // ULOŽ ZMENY!
        }
        Err(()) => println!("Nenájdená"),
    }
}

Keď uložiť:

  • pridaj_knihu — áno (pridávaš)
  • odstran_knihu — áno (mažeš)
  • daj_knihu_podla_isbn — nie (len čítaš)
  • daj_knihy_autora — nie
  • vypis_vydavatelstva_a_pocet_knih — nie

Pravidlo 5: &isbn vs isbn — referencie v argumentoch

Pozri sa čo metóda chce. Ak chce &str, daj referenciu na String.

// Metóda chce: isbn: &str
fn daj_knihu_podla_isbn(&self, isbn: &str) -> Option<&Kniha>

// Ty máš: isbn: String (z clapu)
// Volanie:
kniznica.daj_knihu_podla_isbn(&isbn)  // & premení String na &str

Vždy keď metóda berie &str a ty máš String, daj &:

kniznica.daj_knihu_podla_isbn(&isbn);     // String → &str
kniznica.daj_knihy_autora(&autor);        // String → &str
kniznica.odstran_knihu(&isbn);            // String → &str
kniznica.daj_knihy_podla_stavu(stav);     // Stav sa predáva priamo (nie referencia)

Tvoj kód opravený

use clap::{Parser, Subcommand};
use std::path::PathBuf;
use riesenie1::Kniznica;

#[derive(Parser, Debug)]
struct Args {
    #[command(subcommand)]
    cmd: Sc,
}

#[derive(Subcommand, Debug)]
pub enum Sc {
    DajKnihuIsbn {
        cesta: PathBuf,
        isbn: String,
    },
    DajKnihyAutora {
        cesta: PathBuf,
        autor: String,
    },
    OdstranKnihu {
        cesta: PathBuf,
        isbn: String,
    },
    VypisVydavatelstva {
        cesta: PathBuf,
    },
}

fn main() {
    let args = Args::parse();

    match args.cmd {
        Sc::DajKnihuIsbn { cesta, isbn } => {
            // 1. Načítaj
            let kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
            // 2. Zavolaj na inštancii
            // 3. Spracuj výsledok
            match kniznica.daj_knihu_podla_isbn(&isbn) {
                Some(kniha) => println!("{}", kniha),
                None => println!("Kniha s ISBN {} nenájdená", isbn),
            }
        }
        Sc::DajKnihyAutora { cesta, autor } => {
            let kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
            let knihy = kniznica.daj_knihy_autora(&autor);
            if knihy.is_empty() {
                println!("Žiadne knihy od autora {}", autor);
            } else {
                for kniha in &knihy {
                    println!("{}", kniha);
                }
            }
        }
        Sc::OdstranKnihu { cesta, isbn } => {
            // mut! lebo odstran_knihu je &mut self
            let mut kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
            match kniznica.odstran_knihu(&isbn) {
                Ok(kniha) => {
                    println!("Odstránená: {}", kniha);
                    kniznica.uloz_do_suboru(&cesta);  // ULOŽ!
                }
                Err(()) => println!("Kniha s ISBN {} nenájdená", isbn),
            }
        }
        Sc::VypisVydavatelstva { cesta } => {
            let kniznica = Kniznica::nacitaj_zo_suboru(&cesta).unwrap_or_default();
            // Táto metóda sama vypíše — len ju zavolaj
            kniznica.vypis_vydavatelstva_a_pocet_knih();
        }
    }
}

Cvičenie: Doplň match arms

Dopíš chýbajúce časti. Signatúry metód sú v komentároch.

// SIGNATÚRY:
// fn nacitaj_zo_suboru(cesta: &PathBuf) -> Option<Kontakty>
// fn uloz_do_suboru(&self, cesta: &PathBuf) -> bool
// fn pridaj(&mut self, kontakt: Kontakt) -> Result<(), ()>
// fn odstran(&mut self, meno: &str) -> Result<Kontakt, ()>
// fn hladaj(&self, meno: &str) -> Option<&Kontakt>
// fn vsetky(&self) -> Vec<&Kontakt>

match args.cmd {
    Sc::Pridaj { cesta, meno, telefon } => {
        // TODO: načítaj (mut!), vytvor Kontakt, pridaj, ulož ak ok
    }
    Sc::Odstran { cesta, meno } => {
        // TODO: načítaj (mut!), odstráň, vypíš výsledok, ulož ak ok
    }
    Sc::Hladaj { cesta, meno } => {
        // TODO: načítaj, hľadaj, vypíš Some/None
    }
    Sc::Vypis { cesta } => {
        // TODO: načítaj, zavolaj vsetky(), iteruj a vypíš
    }
}

Skús to vyplniť sám. Ak nevieš, pozri na opravený kód vyššie — vzor je vždy rovnaký:

  1. let (mut) x = Typ::nacitaj_zo_suboru(&cesta).unwrap_or_default();
  2. let vysledok = x.metoda(&arg);
  3. match/if/for na výsledku
  4. Ak &mut self metóda → x.uloz_do_suboru(&cesta);