{"id":"inheritance-access","slug":"protected","title":"private, protected and public in a subclass","text":"A subclass object holds everything its superclass has, private variables too. But the subclass's own code may use only what the superclass lets it use. This step is about those rules.\n\n### private stays private\n\nThe bank from step 3 wants its savings accounts to earn interest. A first try at `addInterest` changes the balance directly:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        SavingsAccount savings = new SavingsAccount(\"Mia\", 500, 3);\n        savings.addInterest();\n    }\n}\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    private int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n}\n// ==== SavingsAccount.java ====\npublic class SavingsAccount extends BankAccount {\n    private int interestPercent;\n\n    public SavingsAccount(String owner, int balance, int interestPercent) {\n        super(owner, balance);\n        this.interestPercent = interestPercent;\n    }\n\n    public void addInterest() {\n        int interest = this.getBalance() * this.interestPercent / 100;\n        this.balance += interest;\n    }\n}\n```\n\n```javac\nSavingsAccount.java:11: error: balance has private access in BankAccount\n        this.balance += interest;\n            ^\n1 error\n```\n\nEvery SavingsAccount object has a balance: it's in the BankAccount part of the object. But `private` means that only BankAccount's own code may use the variable, and SavingsAccount's code isn't BankAccount's code. The same goes for private methods: a subclass can't call them.\n\n### Use the superclass's public methods\n\nUsually the best fix is to use what BankAccount offers everyone. `getBalance()` gives the balance, and `deposit(...)` adds to it:\n\n```java\npublic void addInterest() {\n    int interest = this.getBalance() * this.interestPercent / 100;\n    this.deposit(interest);\n}\n```\n\nThis way BankAccount stays the only class that changes the balance directly, and its rules still hold: `deposit` ignores an amount of 0 or less, so interest can't sneak in a negative amount.\n\n### protected\n\nSometimes the public methods aren't enough. A checking account may go below zero, down to its overdraft limit. In the program below, BankAccount has a `withdraw` that refuses to take more than the balance, and none of its public methods can make a balance negative. So BankAccount marks the balance **protected**: its subclasses may use it directly.\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        BankAccount plain = new BankAccount(\"Leo\", 100);\n        plain.withdraw(150);\n        System.out.println(plain.getBalance());\n\n        CheckingAccount checking = new CheckingAccount(\"Ada\", 100, 200);\n        checking.withdraw(150);\n        System.out.println(checking.getBalance());\n\n        SavingsAccount savings = new SavingsAccount(\"Mia\", 500, 3);\n        savings.addInterest();\n        System.out.println(savings.getBalance());\n    }\n}\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    protected int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance) {\n            this.balance -= amount;\n        }\n    }\n}\n// ==== CheckingAccount.java ====\npublic class CheckingAccount extends BankAccount {\n    private int overdraftLimit;\n\n    public CheckingAccount(String owner, int balance, int overdraftLimit) {\n        super(owner, balance);\n        this.overdraftLimit = overdraftLimit;\n    }\n\n    @Override\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance + this.overdraftLimit) {\n            this.balance -= amount;\n        }\n    }\n}\n// ==== SavingsAccount.java ====\npublic class SavingsAccount extends BankAccount {\n    private int interestPercent;\n\n    public SavingsAccount(String owner, int balance, int interestPercent) {\n        super(owner, balance);\n        this.interestPercent = interestPercent;\n    }\n\n    public void addInterest() {\n        int interest = this.getBalance() * this.interestPercent / 100;\n        this.deposit(interest);\n    }\n}\n```\n\n```output\n100\n-50\n515\n```\n\n- The plain account refuses to pay out 150 from 100. CheckingAccount overrides `withdraw` with its own rule, and changes `this.balance` directly, which `protected` allows.\n- SavingsAccount still uses the public methods. `protected` allows direct use; it doesn't require it.\n- `protected` also lets in every class in the same **package**. A package is a group of classes that belong together, such as Java's own `java.util`. The programs in this course have no `package` line, so all their classes are in one package, the default one, and there even `Main` could use `balance` directly. So in these programs, `protected` is more a note to other programmers (\"subclasses may use this\") than a lock.\n\n### The four levels\n\n| Written before a variable or method | Who can use it |\n| --- | --- |\n| `private` | only the class itself |\n| nothing | classes in the same package |\n| `protected` | classes in the same package, and subclasses |\n| `public` | every class |\n\nA good habit: keep instance variables `private`, and let subclasses work through methods. Make a variable `protected` only when the subclasses really need it, as CheckingAccount did.\n\nOne more rule: an overriding method can't be less visible than the method it overrides. Object's `toString` is `public`, so a `toString` that is `private`, `protected` or has nothing written before it doesn't compile: javac says `attempting to assign weaker access privileges; was public`.\n","task":"The bank's bonus account adds 5 dollars to every deposit of 100 or more. `BonusAccount`'s `deposit` doesn't compile, since the balance is private in BankAccount. Rewrite it with BankAccount's public methods, and don't change `BankAccount.java`: call BankAccount's own `deposit` with `super.deposit(...)`, once for the amount and once more for a bonus. A deposit of 0 or less adds nothing, and gets no bonus. The check runs:\n\n```java\nBonusAccount account = new BonusAccount(\"Ada\", 50);\naccount.deposit(120);\nSystem.out.println(account.getBalance());\naccount.deposit(40);\nSystem.out.println(account.getBalance());\naccount.deposit(-100);\nSystem.out.println(account.getBalance());\n```\n\nand expects:\n\n```\n175\n215\n215\n```\n","kind":"code","seed":"// ==== BonusAccount.java ====\npublic class BonusAccount extends BankAccount {\n\n    public BonusAccount(String owner, int balance) {\n        super(owner, balance);\n    }\n\n    @Override\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n        if (amount >= 100) {\n            this.balance += 5;\n        }\n    }\n}\n\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    private int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public String getOwner() {\n        return this.owner;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        BonusAccount account = new BonusAccount(\"Ada\", 50);\n        account.deposit(120);\n        System.out.println(account.getBalance());\n        account.deposit(40);\n        System.out.println(account.getBalance());\n        account.deposit(-100);\n        System.out.println(account.getBalance());\n    }\n}\n","solution":"// ==== BonusAccount.java ====\npublic class BonusAccount extends BankAccount {\n\n    public BonusAccount(String owner, int balance) {\n        super(owner, balance);\n    }\n\n    @Override\n    public void deposit(int amount) {\n        super.deposit(amount);\n        if (amount >= 100) {\n            super.deposit(5);\n        }\n    }\n}\n\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    private int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public String getOwner() {\n        return this.owner;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        BonusAccount account = new BonusAccount(\"Ada\", 50);\n        account.deposit(120);\n        System.out.println(account.getBalance());\n        account.deposit(40);\n        System.out.println(account.getBalance());\n        account.deposit(-100);\n        System.out.println(account.getBalance());\n    }\n}\n","hints":["BonusAccount overrides `deposit`, so a plain `deposit(...)` inside it would call BonusAccount's own method again. `super.deposit(amount)` calls BankAccount's version, which already ignores amounts of 0 or less.","After `super.deposit(amount);`, add the bonus with `if (amount >= 100) { super.deposit(5); }`."],"tests":[{"name":"Test 1","stdin":"","call":"BonusAccount account = new BonusAccount(\"Ada\", 50);\naccount.deposit(120);\nSystem.out.println(account.getBalance());\naccount.deposit(40);\nSystem.out.println(account.getBalance());\naccount.deposit(-100);\nSystem.out.println(account.getBalance());\n","expect":"175\n215\n215","hidden":false},{"name":"Test 2","stdin":"","call":"BonusAccount account = new BonusAccount(\"Ben\", 0);\naccount.deposit(99);\nSystem.out.println(account.getBalance());\naccount.deposit(100);\nSystem.out.println(account.getBalance());\naccount.deposit(0);\naccount.deposit(1000);\nSystem.out.println(account.getBalance() + \" \" + account.getOwner());\n","expect":"99\n204\n1209 Ben","hidden":true},{"name":"Test 3","stdin":"","call":"BonusAccount first = new BonusAccount(\"Cy\", 10);\nBonusAccount second = new BonusAccount(\"Dee\", 10);\nfirst.deposit(300);\nSystem.out.println(first.getBalance() + \" \" + second.getBalance());\n","expect":"315 10","hidden":true}],"require":[{"pattern":"\\bprivate\\s+int\\s+balance\\b","message":"Keep `balance` private in BankAccount, and use its public methods from BonusAccount."},{"pattern":"\\bsuper\\s*\\.\\s*deposit\\s*\\(","message":"Call BankAccount's own `deposit` with `super.deposit(...)`."}],"forbid":[{"pattern":"\\bprotected\\b","message":"Don't make anything protected here: BankAccount's public `deposit` is enough."}],"more":[{"task":"A museum's exhibits have a condition from 0 to 100, which drops as they age. Only a restorer may raise it again, so `Exhibit` has no public method for that. Paintings can be restored. In `Exhibit.java`, make `condition` protected (not public). Then, in `Painting.java`, write the method `restore()`, which raises the condition by 30, but never above 100. The check runs:\n\n```java\nPainting dawn = new Painting(\"Harbor at Dawn\", 50);\ndawn.restore();\nSystem.out.println(dawn);\ndawn.restore();\nSystem.out.println(dawn);\ndawn.age(15);\nSystem.out.println(dawn.getCondition());\n```\n\nand expects:\n\n```\nHarbor at Dawn, condition 80\nHarbor at Dawn, condition 100\n85\n```\n","kind":"code","seed":"// ==== Painting.java ====\npublic class Painting extends Exhibit {\n\n    public Painting(String name, int condition) {\n        super(name, condition);\n    }\n\n    // Write the method restore here.\n}\n\n// ==== Exhibit.java ====\npublic class Exhibit {\n    private String name;\n    private int condition;\n\n    public Exhibit(String name, int condition) {\n        this.name = name;\n        this.condition = condition;\n    }\n\n    public int getCondition() {\n        return this.condition;\n    }\n\n    public void age(int years) {\n        this.condition -= years;\n        if (this.condition < 0) {\n            this.condition = 0;\n        }\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \", condition \" + this.condition;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Painting dawn = new Painting(\"Harbor at Dawn\", 50);\n        dawn.restore();\n        System.out.println(dawn);\n        dawn.restore();\n        System.out.println(dawn);\n        dawn.age(15);\n        System.out.println(dawn.getCondition());\n    }\n}\n","solution":"// ==== Painting.java ====\npublic class Painting extends Exhibit {\n\n    public Painting(String name, int condition) {\n        super(name, condition);\n    }\n\n    public void restore() {\n        this.condition += 30;\n        if (this.condition > 100) {\n            this.condition = 100;\n        }\n    }\n}\n\n// ==== Exhibit.java ====\npublic class Exhibit {\n    private String name;\n    protected int condition;\n\n    public Exhibit(String name, int condition) {\n        this.name = name;\n        this.condition = condition;\n    }\n\n    public int getCondition() {\n        return this.condition;\n    }\n\n    public void age(int years) {\n        this.condition -= years;\n        if (this.condition < 0) {\n            this.condition = 0;\n        }\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \", condition \" + this.condition;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Painting dawn = new Painting(\"Harbor at Dawn\", 50);\n        dawn.restore();\n        System.out.println(dawn);\n        dawn.restore();\n        System.out.println(dawn);\n        dawn.age(15);\n        System.out.println(dawn.getCondition());\n    }\n}\n","hints":["In Exhibit.java, the line becomes `protected int condition;`. Then Painting's code can use `this.condition` as if it were its own.","`restore()` adds 30 with `this.condition += 30;`, and then, if the condition is over 100, sets it to 100, just as `age` keeps it from going below 0."],"tests":[{"name":"Test 1","stdin":"","call":"Painting dawn = new Painting(\"Harbor at Dawn\", 50);\ndawn.restore();\nSystem.out.println(dawn);\ndawn.restore();\nSystem.out.println(dawn);\ndawn.age(15);\nSystem.out.println(dawn.getCondition());\n","expect":"Harbor at Dawn, condition 80\nHarbor at Dawn, condition 100\n85","hidden":false},{"name":"Test 2","stdin":"","call":"Painting kite = new Painting(\"Red Kite\", 0);\nkite.restore();\nSystem.out.println(kite.getCondition());\nkite.restore();\nkite.restore();\nSystem.out.println(kite.getCondition());\nkite.age(200);\nkite.restore();\nSystem.out.println(kite);\n","expect":"30\n90\nRed Kite, condition 30","hidden":true},{"name":"Test 3","stdin":"","call":"Painting full = new Painting(\"Snow\", 100);\nfull.restore();\nSystem.out.println(full.getCondition());\nPainting worn = new Painting(\"Mill\", 70);\nworn.restore();\nSystem.out.println(worn.getCondition());\n","expect":"100\n100","hidden":true}],"require":[{"pattern":"\\bprotected\\s+int\\s+condition\\b","message":"Make the variable protected in Exhibit.java: `protected int condition;`."},{"pattern":"\\bvoid\\s+restore\\s*\\(\\s*\\)","message":"Write the method `public void restore()` in Painting."}],"forbid":[{"pattern":"\\bpublic\\s+int\\s+condition\\b","message":"Don't make `condition` public: then every class could change it. `protected` is for subclasses."}]},{"task":"Here are the bank's classes from the lesson: BankAccount with its balance `protected`, and CheckingAccount, which overrides `withdraw`. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        BankAccount plain = new BankAccount(\"Leo\", 100);\n        CheckingAccount checking = new CheckingAccount(\"Ada\", 100, 50);\n        plain.withdraw(120);\n        checking.withdraw(120);\n        checking.withdraw(40);\n        checking.deposit(10);\n        System.out.println(plain.getBalance());\n        System.out.println(checking.getBalance());\n    }\n}\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    protected int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance) {\n            this.balance -= amount;\n        }\n    }\n}\n// ==== CheckingAccount.java ====\npublic class CheckingAccount extends BankAccount {\n    private int overdraftLimit;\n\n    public CheckingAccount(String owner, int balance, int overdraftLimit) {\n        super(owner, balance);\n        this.overdraftLimit = overdraftLimit;\n    }\n\n    @Override\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance + this.overdraftLimit) {\n            this.balance -= amount;\n        }\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        BankAccount plain = new BankAccount(\"Leo\", 100);\n        CheckingAccount checking = new CheckingAccount(\"Ada\", 100, 50);\n        plain.withdraw(120);\n        checking.withdraw(120);\n        checking.withdraw(40);\n        checking.deposit(10);\n        System.out.println(plain.getBalance());\n        System.out.println(checking.getBalance());\n    }\n}\n// ==== BankAccount.java ====\npublic class BankAccount {\n    private String owner;\n    protected int balance;\n\n    public BankAccount(String owner, int balance) {\n        this.owner = owner;\n        this.balance = balance;\n    }\n\n    public int getBalance() {\n        return this.balance;\n    }\n\n    public void deposit(int amount) {\n        if (amount > 0) {\n            this.balance += amount;\n        }\n    }\n\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance) {\n            this.balance -= amount;\n        }\n    }\n}\n// ==== CheckingAccount.java ====\npublic class CheckingAccount extends BankAccount {\n    private int overdraftLimit;\n\n    public CheckingAccount(String owner, int balance, int overdraftLimit) {\n        super(owner, balance);\n        this.overdraftLimit = overdraftLimit;\n    }\n\n    @Override\n    public void withdraw(int amount) {\n        if (amount > 0 && amount <= this.balance + this.overdraftLimit) {\n            this.balance -= amount;\n        }\n    }\n}\n","hints":["The plain account runs BankAccount's `withdraw`, which refuses 120 from 100. The checking account runs CheckingAccount's, which allows up to the balance plus 50.","After the first withdrawal, the checking balance is -20, so it can pay out at most -20 + 50 = 30, and 40 is refused. `deposit` is inherited from BankAccount."],"tests":[{"name":"Output","stdin":"","expect":"100\n-10","hidden":false}],"require":[],"forbid":[],"lines":["100","-10"]}]}