{"id":"packages-access","slug":"access","title":"Access across packages","text":"Module 34 listed four levels of access: `private`, nothing, `protected` and `public`. While every class was in the default package, only `private` made a difference. Writing nothing, or `protected`, let in the whole package, and the whole program was one package. With packages, the other levels start to matter.\n\n### public and package-private\n\nA class, or a class's constructor, method or variable, with no word in front of it is **package-private**: only the classes of its own package can use it. From another package, only what's `public` can be used. A constructor without `public` is an easy mistake to make, since until now it changed nothing:\n\n```java\nimport quiz.domain.Question;\n\npublic class Main {\n    public static void main(String[] args) {\n        Question planet = new Question(\"Which planet is the largest?\", \"Jupiter\", 2);\n        System.out.println(planet);\n    }\n}\n// ==== quiz/domain/Question.java ====\npackage quiz.domain;\n\npublic class Question {\n    private String prompt;\n    private String answer;\n    private int points;\n\n    Question(String prompt, String answer, int points) {\n        this.prompt = prompt;\n        this.answer = answer;\n        this.points = points;\n    }\n\n    @Override\n    public String toString() {\n        return this.prompt + \" (\" + this.points + \" points)\";\n    }\n}\n```\n\n```javac\nMain.java:5: error: Question(String,String,int) is not public in Question; cannot be accessed from outside package\n        Question planet = new Question(\"Which planet is the largest?\", \"Jupiter\", 2);\n                          ^\n1 error\n```\n\nThe message names the constructor by its parameter types, and the fix is `public Question(...)`. The same rule holds for the rest of a class:\n\n- A method without `public` gives `getPoints() is not public in Question; cannot be accessed from outside package`.\n- A class written `class Question`, without `public`, can't be used outside its package at all, not even named in an import: `Question is not public in quiz.domain; cannot be accessed from outside package`.\n\nSo a class that other packages use is `public`, and so are the constructors and methods they call. Instance variables stay `private`, as always.\n\n### Package-private on purpose\n\nSometimes a class is meant only for its own package. The quiz's Scorer now also finds the best streak, the most right answers in a row. It leaves the counting to a small helper class, `Streak`, which has no `public` anywhere:\n\n```java\nimport quiz.domain.Question;\nimport quiz.logic.Scorer;\n\npublic class Main {\n    public static void main(String[] args) {\n        Question planet = new Question(\"Which planet is the largest?\", \"Jupiter\", 2);\n        Question gold = new Question(\"What is the chemical symbol for gold?\", \"Au\", 3);\n        Question spider = new Question(\"How many legs does a spider have?\", \"8\", 2);\n        Scorer scorer = new Scorer();\n        scorer.answer(planet, \"Jupiter\");\n        scorer.answer(gold, \"Au\");\n        scorer.answer(spider, \"6\");\n        scorer.answer(planet, \"jupiter\");\n        System.out.println(\"Score: \" + scorer.getScore());\n        System.out.println(\"Best streak: \" + scorer.getBestStreak());\n    }\n}\n// ==== quiz/domain/Question.java ====\npackage quiz.domain;\n\npublic class Question {\n    private String prompt;\n    private String answer;\n    private int points;\n\n    public Question(String prompt, String answer, int points) {\n        this.prompt = prompt;\n        this.answer = answer;\n        this.points = points;\n    }\n\n    public boolean isRight(String reply) {\n        return reply.trim().equalsIgnoreCase(this.answer);\n    }\n\n    public int getPoints() {\n        return this.points;\n    }\n}\n// ==== quiz/logic/Scorer.java ====\npackage quiz.logic;\n\nimport quiz.domain.Question;\n\npublic class Scorer {\n    private int score;\n    private Streak streak;\n\n    public Scorer() {\n        this.score = 0;\n        this.streak = new Streak();\n    }\n\n    public boolean answer(Question question, String reply) {\n        if (question.isRight(reply)) {\n            this.score += question.getPoints();\n            this.streak.right();\n            return true;\n        }\n        this.streak.wrong();\n        return false;\n    }\n\n    public int getScore() {\n        return this.score;\n    }\n\n    public int getBestStreak() {\n        return this.streak.getBest();\n    }\n}\n// ==== quiz/logic/Streak.java ====\npackage quiz.logic;\n\nclass Streak {\n    private int current;\n    private int best;\n\n    void right() {\n        this.current++;\n        if (this.current > this.best) {\n            this.best = this.current;\n        }\n    }\n\n    void wrong() {\n        this.current = 0;\n    }\n\n    int getBest() {\n        return this.best;\n    }\n}\n```\n\n```output\nScore: 7\nBest streak: 2\n```\n\n- Scorer and Streak are in the same package, `quiz.logic`, so Scorer uses everything Streak has.\n- Main can't import Streak or write `quiz.logic.Streak`: javac would say `Streak is not public in quiz.logic; cannot be accessed from outside package`. Main works through Scorer's public methods.\n- A package's public classes are what the rest of the program uses. Its package-private classes are details: the package can change or remove them, and nothing outside can break, since nothing outside can use them. It's the idea of `private`, one level up: from a class to a package.\n\n### protected across packages\n\n`protected` lets in the classes of its package, and also the subclasses, even those in other packages. Say a question's `getAnswer()` is `protected`: most classes shouldn't peek at the answer, but a subclass may need it. A question with a hint, in a package `quiz.hints` of its own, gives the answer's first letter:\n\n```java\nimport quiz.hints.HintedQuestion;\n\npublic class Main {\n    public static void main(String[] args) {\n        HintedQuestion planet = new HintedQuestion(\"Which planet is the largest?\", \"Jupiter\", 2);\n        System.out.println(planet.hint());\n        System.out.println(planet.isRight(\"jupiter\"));\n    }\n}\n// ==== quiz/domain/Question.java ====\npackage quiz.domain;\n\npublic class Question {\n    private String prompt;\n    private String answer;\n    private int points;\n\n    public Question(String prompt, String answer, int points) {\n        this.prompt = prompt;\n        this.answer = answer;\n        this.points = points;\n    }\n\n    public boolean isRight(String reply) {\n        return reply.trim().equalsIgnoreCase(this.answer);\n    }\n\n    protected String getAnswer() {\n        return this.answer;\n    }\n}\n// ==== quiz/hints/HintedQuestion.java ====\npackage quiz.hints;\n\nimport quiz.domain.Question;\n\npublic class HintedQuestion extends Question {\n    public HintedQuestion(String prompt, String answer, int points) {\n        super(prompt, answer, points);\n    }\n\n    public String hint() {\n        return \"It starts with \" + this.getAnswer().charAt(0);\n    }\n}\n```\n\n```output\nIt starts with J\ntrue\n```\n\nHintedQuestion is in another package, but it's a subclass of Question, so it may call `getAnswer()`. Main is neither in `quiz.domain` nor a subclass: if it called `planet.getAnswer()`, javac would say `getAnswer() has protected access in Question`. Subclasses in other packages are common: a class of your own that extends a class of a library is one.\n\nThere's one limit. From another package, a subclass may use an object's protected method or variable only through its own type: for example on `this`, or on a variable whose type is `HintedQuestion` (or a class that extends it). On a variable of type `Question`, such as a parameter `Question other`, javac gives the same `getAnswer() has protected access in Question` that Main gets, even when the object in it is a HintedQuestion.\n\n### The four levels, with packages\n\n| Written in front | Its own class | Its package | Subclasses in other packages | Everyone else |\n| --- | --- | --- | --- | --- |\n| `private` | yes | no | no | no |\n| nothing | yes | yes | no | no |\n| `protected` | yes | yes | yes, through their own type | no |\n| `public` | yes | yes | yes | yes |\n\nThe table is for classes and their members. A method an interface lists is public even with nothing written in front (module 35).\n\nOne more thing: `quiz` and `quiz.domain` are two separate packages. The folder `domain` is inside the folder `quiz`, but for access that means nothing: a class of the package `quiz` can't use what `quiz.domain` keeps package-private.\n","task":"A vending machine's program keeps its snacks in the package `vending.domain`, but `Main.java` doesn't compile: Snack keeps too much to its own package. Make public exactly what Main uses, and nothing more. `refill` is only for the machine's service classes in `vending.domain`, so it stays package-private. Don't change `Main.java`. The program should print:\n\n```\ntrue\nfalse\nPretzels: 0 left, 150 cents\n```\n","kind":"code","seed":"// ==== vending/domain/Snack.java ====\npackage vending.domain;\n\nclass Snack {\n    private String name;\n    private int price;\n    private int count;\n\n    Snack(String name, int price, int count) {\n        this.name = name;\n        this.price = price;\n        this.count = count;\n    }\n\n    String getName() {\n        return this.name;\n    }\n\n    public int getPrice() {\n        return this.price;\n    }\n\n    public int getCount() {\n        return this.count;\n    }\n\n    public boolean sell() {\n        if (this.count == 0) {\n            return false;\n        }\n        this.count--;\n        return true;\n    }\n\n    void refill(int count) {\n        this.count += count;\n    }\n}\n\n// ==== Main.java ====\nimport vending.domain.Snack;\n\npublic class Main {\n    public static void main(String[] args) {\n        Snack pretzels = new Snack(\"Pretzels\", 150, 1);\n        System.out.println(pretzels.sell());\n        System.out.println(pretzels.sell());\n        System.out.println(pretzels.getName() + \": \" + pretzels.getCount() + \" left, \" + pretzels.getPrice() + \" cents\");\n    }\n}\n","solution":"// ==== vending/domain/Snack.java ====\npackage vending.domain;\n\npublic class Snack {\n    private String name;\n    private int price;\n    private int count;\n\n    public Snack(String name, int price, int count) {\n        this.name = name;\n        this.price = price;\n        this.count = count;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getPrice() {\n        return this.price;\n    }\n\n    public int getCount() {\n        return this.count;\n    }\n\n    public boolean sell() {\n        if (this.count == 0) {\n            return false;\n        }\n        this.count--;\n        return true;\n    }\n\n    void refill(int count) {\n        this.count += count;\n    }\n}\n\n// ==== Main.java ====\nimport vending.domain.Snack;\n\npublic class Main {\n    public static void main(String[] args) {\n        Snack pretzels = new Snack(\"Pretzels\", 150, 1);\n        System.out.println(pretzels.sell());\n        System.out.println(pretzels.sell());\n        System.out.println(pretzels.getName() + \": \" + pretzels.getCount() + \" left, \" + pretzels.getPrice() + \" cents\");\n    }\n}\n","hints":["javac's first messages are about the class itself: `Snack is not public in vending.domain`. Write `public class Snack`, and run again: then javac gets to the constructor and to `getName`.","Put `public` in front of the constructor and of `getName`. Leave `refill` as it is: Main doesn't call it."],"tests":[{"name":"The program's output","stdin":"","expect":"true\nfalse\nPretzels: 0 left, 150 cents","hidden":false},{"name":"Test 2","stdin":"","call":"Snack gum = new Snack(\"Gum\", 90, 3);\ngum.sell();\nSystem.out.println(gum.getName() + \" \" + gum.getCount() + \" \" + gum.getPrice());\nSnack chips = new Snack(\"Chips\", 120, 0);\nSystem.out.println(chips.sell() + \" \" + chips.getName());\n","expect":"Gum 2 90\nfalse Chips","hidden":true}],"require":[],"forbid":[{"pattern":"\\b(?:public|protected|private)\\s+void\\s+refill\\b","message":"Leave `refill` package-private, with nothing in front: only the classes of `vending.domain` should refill snacks, and Main doesn't call it."}],"more":[{"task":"The vending company's machines get screens that scroll ads, and the ad screens get a package of their own, `vending.ads`. `Screen`, in `vending.domain`, is ready: it keeps the text it shows in `text`, which is protected, for its subclasses. A new Screen shows an empty text, `getText()` returns the text, and `clear()` empties it.\n\nIn `vending/ads/AdScreen.java`, write the class `AdScreen`, which extends `Screen` (import it). It has:\n\n- a constructor `AdScreen(String text)`, which puts the text on the screen\n- `public String scroll()`, which moves the text's first character to its end and returns the new text. An empty text stays empty.\n\nThe check runs:\n\n```java\nAdScreen screen = new AdScreen(\"Cold drinks! \");\nSystem.out.println(screen.scroll());\nSystem.out.println(screen.scroll());\nSystem.out.println(\"Screen: \" + screen.getText());\n```\n\nand expects:\n\n```\nold drinks! C\nld drinks! Co\nScreen: ld drinks! Co\n```\n","kind":"code","seed":"// ==== vending/ads/AdScreen.java ====\npackage vending.ads;\n\n// Import Screen, and write the class AdScreen here.\n\n// ==== vending/domain/Screen.java ====\npackage vending.domain;\n\npublic class Screen {\n    protected String text;\n\n    public Screen() {\n        this.text = \"\";\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void clear() {\n        this.text = \"\";\n    }\n}\n\n// ==== Main.java ====\nimport vending.ads.AdScreen;\n\npublic class Main {\n    public static void main(String[] args) {\n        AdScreen screen = new AdScreen(\"Cold drinks! \");\n        System.out.println(screen.scroll());\n        System.out.println(screen.scroll());\n        System.out.println(\"Screen: \" + screen.getText());\n    }\n}\n","solution":"// ==== vending/ads/AdScreen.java ====\npackage vending.ads;\n\nimport vending.domain.Screen;\n\npublic class AdScreen extends Screen {\n    public AdScreen(String text) {\n        this.text = text;\n    }\n\n    public String scroll() {\n        if (this.text.isEmpty()) {\n            return this.text;\n        }\n        this.text = this.text.substring(1) + this.text.charAt(0);\n        return this.text;\n    }\n}\n\n// ==== vending/domain/Screen.java ====\npackage vending.domain;\n\npublic class Screen {\n    protected String text;\n\n    public Screen() {\n        this.text = \"\";\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void clear() {\n        this.text = \"\";\n    }\n}\n\n// ==== Main.java ====\nimport vending.ads.AdScreen;\n\npublic class Main {\n    public static void main(String[] args) {\n        AdScreen screen = new AdScreen(\"Cold drinks! \");\n        System.out.println(screen.scroll());\n        System.out.println(screen.scroll());\n        System.out.println(\"Screen: \" + screen.getText());\n    }\n}\n","hints":["After the package line comes `import vending.domain.Screen;`, and then `public class AdScreen extends Screen {`. `text` is Screen's protected variable: AdScreen may read and change it although it's in another package, because it's a subclass. The constructor puts the text there.","In `scroll()`, `this.text.substring(1)` is the text without its first character, and `this.text.charAt(0)` is that character. Join them in the other order, keep the result in `this.text` and return it. Check `this.text.isEmpty()` first: an empty text has no first character."],"tests":[{"name":"Test 1","stdin":"","call":"AdScreen screen = new AdScreen(\"Cold drinks! \");\nSystem.out.println(screen.scroll());\nSystem.out.println(screen.scroll());\nSystem.out.println(\"Screen: \" + screen.getText());\n","expect":"old drinks! C\nld drinks! Co\nScreen: ld drinks! Co","hidden":false},{"name":"Test 2","stdin":"","call":"AdScreen screen = new AdScreen(\"abc\");\nSystem.out.println(screen.getText() + \" \" + screen.scroll() + \" \" + screen.scroll() + \" \" + screen.scroll() + \" \" + screen.getText());\nscreen.clear();\nSystem.out.println(\"[\" + screen.scroll() + \"] [\" + screen.getText() + \"]\");\nAdScreen blank = new AdScreen(\"\");\nSystem.out.println(\"[\" + blank.scroll() + \"]\");\nAdScreen one = new AdScreen(\"X\");\nSystem.out.println(one.scroll() + one.scroll() + one.getText());\n","expect":"abc bca cab abc abc\n[] []\n[]\nXXX","hidden":true}],"require":[{"pattern":"\\bclass\\s+AdScreen\\s+extends\\s+Screen\\b","message":"Write the header as `public class AdScreen extends Screen`, after importing Screen."}],"forbid":[]},{"task":"A laundromat's program has three classes that use `Machine`, which is in the package `laundromat.domain`:\n\n- `Technician`, in the same package, calls `stopNow()`, to stop a machine in the middle of a cycle\n- `Dryer`, a subclass of Machine in the package `laundromat.dryers`, changes `minutesLeft` directly, to add time to a running cycle\n- `Main`, in the default package, creates machines and calls `start` and `pass`\n\nIn `Machine.java`, only the class and `toString` have a word in front of them yet, so the program doesn't compile. Give each variable, the constructor and each method the most restricted access that still works: `private` for what only Machine itself uses, nothing for what only its own package uses, `protected` for what a subclass in another package needs, and `public` for what Main uses. Change only `Machine.java`. The program should print:\n\n```\nMachine 4: 25 minutes left\nMachine 9: 25 minutes left\nMachine 4: free\n```\n","kind":"code","seed":"// ==== laundromat/domain/Machine.java ====\npackage laundromat.domain;\n\npublic class Machine {\n    int number;\n    int minutesLeft;\n\n    Machine(int number) {\n        this.number = number;\n        this.minutesLeft = 0;\n    }\n\n    void start(int minutes) {\n        this.minutesLeft = minutes;\n    }\n\n    void pass(int minutes) {\n        this.minutesLeft -= minutes;\n        if (this.minutesLeft < 0) {\n            this.minutesLeft = 0;\n        }\n    }\n\n    void stopNow() {\n        this.minutesLeft = 0;\n    }\n\n    @Override\n    public String toString() {\n        if (this.minutesLeft == 0) {\n            return \"Machine \" + this.number + \": free\";\n        }\n        return \"Machine \" + this.number + \": \" + this.minutesLeft + \" minutes left\";\n    }\n}\n\n// ==== laundromat/domain/Technician.java ====\npackage laundromat.domain;\n\npublic class Technician {\n    public void stop(Machine machine) {\n        machine.stopNow();\n    }\n}\n\n// ==== laundromat/dryers/Dryer.java ====\npackage laundromat.dryers;\n\nimport laundromat.domain.Machine;\n\npublic class Dryer extends Machine {\n    public Dryer(int number) {\n        super(number);\n    }\n\n    public void addTime(int minutes) {\n        if (this.minutesLeft > 0) {\n            this.minutesLeft += minutes;\n        }\n    }\n}\n\n// ==== Main.java ====\nimport laundromat.domain.Machine;\nimport laundromat.domain.Technician;\nimport laundromat.dryers.Dryer;\n\npublic class Main {\n    public static void main(String[] args) {\n        Machine washer = new Machine(4);\n        Dryer dryer = new Dryer(9);\n        washer.start(45);\n        dryer.start(30);\n        dryer.addTime(15);\n        washer.pass(20);\n        dryer.pass(20);\n        System.out.println(washer);\n        System.out.println(dryer);\n        new Technician().stop(washer);\n        System.out.println(washer);\n    }\n}\n","solution":"// ==== laundromat/domain/Machine.java ====\npackage laundromat.domain;\n\npublic class Machine {\n    private int number;\n    protected int minutesLeft;\n\n    public Machine(int number) {\n        this.number = number;\n        this.minutesLeft = 0;\n    }\n\n    public void start(int minutes) {\n        this.minutesLeft = minutes;\n    }\n\n    public void pass(int minutes) {\n        this.minutesLeft -= minutes;\n        if (this.minutesLeft < 0) {\n            this.minutesLeft = 0;\n        }\n    }\n\n    void stopNow() {\n        this.minutesLeft = 0;\n    }\n\n    @Override\n    public String toString() {\n        if (this.minutesLeft == 0) {\n            return \"Machine \" + this.number + \": free\";\n        }\n        return \"Machine \" + this.number + \": \" + this.minutesLeft + \" minutes left\";\n    }\n}\n\n// ==== laundromat/domain/Technician.java ====\npackage laundromat.domain;\n\npublic class Technician {\n    public void stop(Machine machine) {\n        machine.stopNow();\n    }\n}\n\n// ==== laundromat/dryers/Dryer.java ====\npackage laundromat.dryers;\n\nimport laundromat.domain.Machine;\n\npublic class Dryer extends Machine {\n    public Dryer(int number) {\n        super(number);\n    }\n\n    public void addTime(int minutes) {\n        if (this.minutesLeft > 0) {\n            this.minutesLeft += minutes;\n        }\n    }\n}\n\n// ==== Main.java ====\nimport laundromat.domain.Machine;\nimport laundromat.domain.Technician;\nimport laundromat.dryers.Dryer;\n\npublic class Main {\n    public static void main(String[] args) {\n        Machine washer = new Machine(4);\n        Dryer dryer = new Dryer(9);\n        washer.start(45);\n        dryer.start(30);\n        dryer.addTime(15);\n        washer.pass(20);\n        dryer.pass(20);\n        System.out.println(washer);\n        System.out.println(dryer);\n        new Technician().stop(washer);\n        System.out.println(washer);\n    }\n}\n","hints":["Go through Machine's parts one by one and ask who uses each. `number` appears only in Machine's own code. `minutesLeft` is also used by Dryer, a subclass in another package. Main calls the constructor, `start` and `pass`. Only Technician, in Machine's package, calls `stopNow`.","So: `private int number;`, `protected int minutesLeft;`, `public Machine(int number)`, `public void start(...)` and `public void pass(...)`, and `stopNow()` stays as it is, with nothing in front."],"tests":[{"name":"The program's output","stdin":"","expect":"Machine 4: 25 minutes left\nMachine 9: 25 minutes left\nMachine 4: free","hidden":false},{"name":"Test 2","stdin":"","call":"Dryer dryer = new Dryer(2);\ndryer.addTime(10);\nSystem.out.println(dryer);\ndryer.start(15);\ndryer.addTime(10);\ndryer.pass(5);\nSystem.out.println(dryer);\nMachine washer = new Machine(7);\nwasher.start(60);\nnew Technician().stop(washer);\nSystem.out.println(washer);\n","expect":"Machine 2: free\nMachine 2: 20 minutes left\nMachine 7: free","hidden":true}],"require":[{"pattern":"\\bprivate\\s+int\\s+number\\b","message":"Only Machine's own code uses `number`, so it can be `private`."},{"pattern":"\\bprotected\\s+int\\s+minutesLeft\\b","message":"Dryer, a subclass in another package, changes `minutesLeft` directly, and no other class outside the package does: make it `protected`, not `public`."}],"forbid":[{"pattern":"\\b(?:public|protected|private)\\s+void\\s+stopNow\\b","message":"Only Technician, in Machine's own package, calls `stopNow`: leave it package-private, with nothing in front."}]}]}