Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

05.11 Getters a setters

Výuka

Proč getters a setters?

Getters a setters jsou speciální metody, které se chovají jako vlastnosti. Umožňují kontrolovat přístup a modifikaci dat objektu.

Proč to potřebujeme?

  • Enkapsulace - Kontrola přístupu k datům
  • Validace - Ověř data před uložením
  • Vypočítané vlastnosti - Hodnota se vypočítá za běhu
  • Backwards compatibility - Změň implementaci bez změny API

Představ si to jako: Recepce v hotelu. Místo přímého přístupu do pokojů (direct property access) musíš projít recepcí (getter/setter), která zkontroluje tvůj klíč (validace) a případně ti dá informace (vypočítaná hodnota).

Jak to funguje?

Getters a setters:
1. get propName() { ... } - getter, volá se při čtení obj.propName
2. set propName(value) { ... } - setter, volá se při zápisu obj.propName = value
3. Chovají se jako vlastnosti (ne metody!)
4. Žádné závorky při volání
5. Můžeš mít get bez set (read-only) nebo set bez get

Klíčové koncepty

  • Getter - get propName() - čtení vlastnosti
  • Setter - set propName(value) - zápis vlastnosti
  • Accessor properties - vlastnosti s get/set
  • Data properties - běžné vlastnosti
  • Vypočítaná hodnota - getter vrací vypočítanou hodnotu
  • Validace - setter kontroluje hodnotu před uložením

JavaScript

Příklad 1: Základní getter a setter

const person = {
  firstName: 'Alice',
  lastName: 'Johnson',

  // Getter - čtení vlastnosti
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },

  // Setter - zápis vlastnosti
  set fullName(name) {
    const parts = name.split(' ');
    this.firstName = parts[0];
    this.lastName = parts[1];
  }
};

// Getter - volá se BEZ závorek (jako vlastnost!)
console.log(person.fullName);
// → Alice Johnson

// Setter - přiřazení jako k vlastnosti
person.fullName = 'Bob Smith';
console.log(person.firstName);  // → Bob
console.log(person.lastName);   // → Smith
console.log(person.fullName);   // → Bob Smith

Co se stalo?

  • Getter get fullName() - volá se při čtení person.fullName
  • Setter set fullName(value) - volá se při zápisu person.fullName = ...
  • Žádné závorky - chovají se jako vlastnosti!
  • Užitečné pro vypočítané hodnoty a validaci

Příklad 2: Validace v setteru

const user = {
  _age: 0,  // Konvence: _ znamená "internal/private"

  get age() {
    return this._age;
  },

  set age(value) {
    // Validace
    if (typeof value !== 'number') {
      throw new TypeError('Age must be a number');
    }

    if (value < 0 || value > 150) {
      throw new RangeError('Age must be between 0 and 150');
    }

    this._age = value;
  }
};

user.age = 25;
console.log(user.age);
// → 25

// Pokus o neplatnou hodnotu
try {
  user.age = -5;
} catch (error) {
  console.log(error.message);
  // → Age must be between 0 and 150
}

try {
  user.age = 'invalid';
} catch (error) {
  console.log(error.message);
  // → Age must be a number
}

Co se stalo?

  • Setter validuje hodnotu před uložením
  • _age je "internal" vlastnost (konvence, ne skutečná ochrana!)
  • Kontrola typu a rozsahu - throw error pokud neplatné
  • Užitečné pro data integrity

Příklad 3: Read-only vlastnost (jen getter)

const rectangle = {
  width: 10,
  height: 5,

  // Jen getter - vypočítaná vlastnost (read-only)
  get area() {
    return this.width * this.height;
  },

  get perimeter() {
    return 2 * (this.width + this.height);
  }
};

console.log(rectangle.area);
// → 50

console.log(rectangle.perimeter);
// → 30

// Změna width/height aktualizuje area automaticky
rectangle.width = 20;
console.log(rectangle.area);
// → 100 (20 * 5)

// Pokus o zápis - žádný setter!
rectangle.area = 200;  // Ignoruje se v non-strict mode
console.log(rectangle.area);
// → 100 (nezměnilo se)

// V strict mode by to byl error:
'use strict';
// rectangle.area = 200;  // TypeError: Cannot set property area

Co se stalo?

  • Read-only vlastnost - jen getter, bez setteru
  • Vypočítaná hodnota - vrací se za běhu
  • Pokus o zápis se ignoruje (non-strict) nebo error (strict mode)
  • Užitečné pro derived properties

Příklad 4: Write-only vlastnost (jen setter)

const logger = {
  _logs: [],

  // Jen setter - zápis logů
  set message(msg) {
    const timestamp = new Date().toISOString();
    this._logs.push(`[${timestamp}] ${msg}`);
    console.log(`Logged: ${msg}`);
  },

  // Metoda pro získání všech logů
  getLogs() {
    return this._logs;
  }
};

// Setter
logger.message = 'Application started';
// → Logged: Application started

logger.message = 'User logged in';
// → Logged: User logged in

// Čtení přes metodu (ne getter)
console.log(logger.getLogs());
// → ['[2025-12-19T...] Application started', '[2025-12-19T...] User logged in']

// Pokus o čtení message - undefined (žádný getter)
console.log(logger.message);
// → undefined

Co se stalo?

  • Write-only vlastnost - jen setter, bez getteru
  • Setter zpracovává hodnotu (timestamp, logging)
  • Čtení vrací undefined (žádný getter)
  • Užitečné pro command-like operations

Příklad 5: Lazy loading s getterem

const config = {
  _connection: null,

  get connection() {
    // Lazy initialization - vytvoř jen když potřebuješ
    if (!this._connection) {
      console.log('Creating connection...');
      this._connection = {
        host: 'localhost',
        port: 3000,
        connected: true
      };
    }
    return this._connection;
  }
};

// První přístup - vytvoří connection
console.log(config.connection);
// → Creating connection...
// → { host: 'localhost', port: 3000, connected: true }

// Druhý přístup - použije cached connection
console.log(config.connection);
// → { host: 'localhost', port: 3000, connected: true }
// (žádný "Creating connection...")

Co se stalo?

  • Lazy loading - vytvoř objekt až když je potřeba
  • Getter zkontroluje, zda již existuje
  • Cachování - další přístupy vrací cached hodnotu
  • Užitečné pro expensive operations

Příklad 6: Getters/setters v class

class Temperature {
  constructor(celsius) {
    this._celsius = celsius;
  }

  // Getter pro celsius
  get celsius() {
    return this._celsius;
  }

  // Setter pro celsius
  set celsius(value) {
    if (value < -273.15) {
      throw new Error('Temperature below absolute zero!');
    }
    this._celsius = value;
  }

  // Getter pro fahrenheit (vypočítaná vlastnost)
  get fahrenheit() {
    return this._celsius * 9/5 + 32;
  }

  // Setter pro fahrenheit
  set fahrenheit(value) {
    this.celsius = (value - 32) * 5/9;  // Převod + validace
  }

  // Getter pro kelvin
  get kelvin() {
    return this._celsius + 273.15;
  }
}

const temp = new Temperature(25);

console.log(temp.celsius);     // → 25
console.log(temp.fahrenheit);  // → 77
console.log(temp.kelvin);      // → 298.15

// Nastav fahrenheit
temp.fahrenheit = 100;
console.log(temp.celsius);     // → 37.77... (převedeno)

// Pokus o neplatnou hodnotu
try {
  temp.celsius = -300;
} catch (error) {
  console.log(error.message);
  // → Temperature below absolute zero!
}

Co se stalo?

  • Getters/setters v class - stejná syntaxe jako v objektech
  • Převod jednotek - fahrenheit/kelvin vypočítány z celsius
  • Validace - kontrola absolute zero
  • Užitečné pro data classes a value objects

TypeScript

TypeScript přidává typovou kontrolu getterů a setterů.

Stejné příklady s typy

// Interface s accessor properties
interface Person {
  firstName: string;
  lastName: string;
  fullName: string;  // Accessor property (get/set)
}

// Implementace s getters/setters
class PersonClass {
  firstName: string;
  lastName: string;

  constructor(firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }

  set fullName(name: string) {
    const parts = name.split(' ');
    this.firstName = parts[0];
    this.lastName = parts[1] || '';
  }
}

const person = new PersonClass('Alice', 'Johnson');
const name: string = person.fullName;  // ✅ TypeScript ví, že je string

// Type-safe validation
class User {
  private _age: number = 0;

  get age(): number {
    return this._age;
  }

  set age(value: number) {  // TypeScript kontroluje typ!
    if (value < 0 || value > 150) {
      throw new RangeError('Age must be between 0 and 150');
    }
    this._age = value;
  }
}

const user = new User();
user.age = 25;  // ✅ OK
// user.age = 'invalid';  // ❌ Error: Type 'string' is not assignable to type 'number'

// Read-only property (jen getter)
class Rectangle {
  constructor(public width: number, public height: number) {}

  get area(): number {
    return this.width * this.height;
  }
}

const rect = new Rectangle(10, 5);
const area: number = rect.area;  // ✅ OK
// rect.area = 100;  // ❌ Error: Cannot assign to 'area' because it is a read-only property

// Generic getters/setters
class Container<T> {
  private _value!: T;

  get value(): T {
    return this._value;
  }

  set value(val: T) {
    this._value = val;
  }
}

const stringContainer = new Container<string>();
stringContainer.value = 'hello';  // ✅ OK
const val: string = stringContainer.value;  // ✅ type: string

TypeScript přidává:

  • Typovou kontrolu getter/setter - musí odpovídat typu
  • Read-only detection - varování při zápisu do read-only
  • Private properties - skutečná ochrana (ne jen konvence)
  • Prevenci chyb - upozorní na neplatné typy

Rozdíl JS vs TS

JavaScript:

  • Getters/setters fungují bez typové kontroly
  • _property konvence (ne skutečná ochrana)
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • Getters/setters mají typovou kontrolu
  • private keyword pro skutečnou ochranu
  • Bezpečnější, prevence chyb
// JavaScript - žádná ochrana
const obj = {
  _value: 0,
  get value() { return this._value; }
};
obj._value = 'invalid';  // Žádná kontrola!

// TypeScript - ochrana
class Obj {
  private _value: number = 0;
  get value(): number { return this._value; }
}
const obj = new Obj();
// obj._value = 'invalid';  // ❌ Error: Property '_value' is private

Tip

💡 Používej getters pro vypočítané vlastnosti:

// ✅ Vypočítaná vlastnost přes getter
const obj = {
  width: 10,
  height: 5,
  get area() {
    return this.width * this.height;
  }
};

// Místo metody
const obj = {
  width: 10,
  height: 5,
  getArea() {  // Musíš volat s ()
    return this.width * this.height;
  }
};

💡 Používej setters pro validaci:

// ✅ Validace v setteru
const user = {
  _age: 0,
  set age(value) {
    if (value < 0) throw new Error('Invalid age');
    this._age = value;
  },
  get age() {
    return this._age;
  }
};

// Místo přímého přístupu
user._age = -5;  // Žádná validace!

💡 Používej _ konvenci pro internal properties:

// ✅ Konvence - _ znamená "internal"
const obj = {
  _value: 0,  // Internal
  get value() { return this._value; },
  set value(val) { this._value = val; }
};

// Ale v TypeScript používej private!
class Obj {
  private _value: number = 0;  // Skutečná ochrana
  get value() { return this._value; }
}

Kvíz

Co vypíše tento kód?

const obj = {
  _value: 10,

  get double() {
    return this._value * 2;
  }
};

obj._value = 5;
console.log(obj.double);

- - obj._value = 10 (inicializace)

  • obj._value = 5 - přímá změna _value na 5
  • obj.double - getter vrací this._value * 2 = 5 * 2 = 10

- To by bylo před změnou _value

- To je hodnota _value, ne double

- Getter vrací vypočítanou hodnotu

Důležité: Getter vždy vypočítává hodnotu za běhu - když změníš zdrojová data, getter vrátí novou hodnotu!

Důležité: Getter vždy vypočítává hodnotu za běhu - když změníš zdrojová data, getter vrátí novou hodnotu!

🎯 Závěrečný projekt

Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.

Zobrazit podrobnosti projektu →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

Informace o seriálu

Obtížnost

Délka

Cca 480 minut

Počet videí

8 videí + projekty

Certifikát

Po dokončení obdržíte certifikát


Lekce v této sekci


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě