269 lines
7.7 KiB
Markdown
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` sú `&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);`
|