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

269 lines
7.7 KiB
Markdown

# clap → match → volanie metód — kde robíš chybu
Tvoj problém nie je clap. Clap máš dobre. Tvoj problém je toto:
```rust
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.
```rust
// 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ť.
```rust
// 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ť.
```rust
// 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
```rust
// Čí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.
```rust
// 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 `&`:
```rust
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ý
```rust
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.
```rust
// 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);`