private and public

Any code can change any field of an object. One careless line somewhere in the game, and Kira has negative gold:

class Hero {
    name: string;
    gold: number = 0;

    constructor(name: string) {
        this.name = name;
    }

    earn(amount: number): void {
        this.gold = this.gold + amount;
    }
}

const kira = new Hero("Kira");
kira.earn(50);
kira.gold = kira.gold - 80; // buys a sword for 80 gold
console.log(`${kira.name} has ${kira.gold} gold`);

This prints:

Kira has -30 gold

The class should guard its gold: only its own methods should change it, and they can check the rules. Mark the field private:

class Hero {
    name: string;
    private gold: number = 0;

    constructor(name: string) {
        this.name = name;
    }

    earn(amount: number): void {
        this.gold = this.gold + amount;
    }

    spend(amount: number): boolean {
        if (amount > this.gold) {
            return false;
        }
        this.gold = this.gold - amount;
        return true;
    }

    getGold(): number {
        return this.gold;
    }
}

const kira = new Hero("Kira");
kira.earn(50);
console.log(kira.spend(80));
console.log(kira.spend(30));
console.log(`${kira.name} has ${kira.getGold()} gold`);

This prints:

false
true
Kira has 20 gold

A private field can be used only inside the class, in its methods, through this. Code outside the class can neither read it nor change it. Add kira.gold = 1000; at the end of the program, and TypeScript reports:

main.ts(31,6): error TS2341: Property 'gold' is private and only accessible within class 'Hero'.

The rest of the game gets to the gold through the methods, and they keep the rules: spend returns false and changes nothing when there isn't enough gold, and getGold lets others read the gold without being able to change it. Fields and methods without private are public: anyone can use them. That's the default. You can also write public explicitly (public name: string;), but most code doesn't.

Like readonly in lesson 4, private is checked only by TypeScript. In JavaScript, gold is an ordinary property, and console.log(kira) still shows it: Hero { name: "Kira", gold: 20 }. JavaScript also has its own private fields, whose names start with # (#gold); those stay hidden even while the program runs. You'll see both kinds in other code; this course uses private.

Typical mistakes: reading a private field from outside the class (add a method that returns it, like getGold), and making a method private that the rest of the program needs to call.

Instructions

Run the program: Lena ends up with negative mana. Add a method cast(cost: number): boolean: if the mage has less mana than cost, it returns false and changes nothing; otherwise, it subtracts cost from mana and returns true. Replace both lines that change lena.mana with console.log(lena.cast(15));. The program prints:

true
false
Lena has 5 mana

So that nobody can get around cast, make mana private: write private in front of the field. TypeScript then reports the last line, which reads lena.mana from outside the class. Add a method getMana(): number and use it in that line. The program prints the same as before.

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

4/9