{"id":"polymorphism-program","slug":"one-list-many-kinds","title":"A program built on polymorphism","text":"Steps 1 and 2 looked at the types an object has, what a variable of each type lets you call, and how to check for a type with `instanceof` and cast to it. This step builds a small program around the idea that makes polymorphism worth having: code that works with one general type, and objects that each do their own thing.\n\n### A payroll\n\nA company pays its staff every month, but not all in the same way. A salaried employee gets a twelfth of a yearly salary. An hourly employee gets an hourly rate times the hours logged. `Employee` is an abstract class that knows the name and leaves the pay to each kind of employee, and `Payroll` keeps them all in one list:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Payroll payroll = new Payroll();\n        payroll.add(new SalariedEmployee(\"Rosa\", 54000));\n\n        HourlyEmployee sam = new HourlyEmployee(\"Sam\", 22);\n        sam.logHours(80);\n        sam.logHours(35);\n        payroll.add(sam);\n\n        payroll.add(new SalariedEmployee(\"Omar\", 61200));\n        payroll.printSlips();\n    }\n}\n// ==== Employee.java ====\npublic abstract class Employee {\n    private String name;\n\n    public Employee(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public abstract int monthlyPay();\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.monthlyPay();\n    }\n}\n// ==== SalariedEmployee.java ====\npublic class SalariedEmployee extends Employee {\n    private int yearlySalary;\n\n    public SalariedEmployee(String name, int yearlySalary) {\n        super(name);\n        this.yearlySalary = yearlySalary;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.yearlySalary / 12;\n    }\n}\n// ==== HourlyEmployee.java ====\npublic class HourlyEmployee extends Employee {\n    private int hourlyRate;\n    private int hours;\n\n    public HourlyEmployee(String name, int hourlyRate) {\n        super(name);\n        this.hourlyRate = hourlyRate;\n        this.hours = 0;\n    }\n\n    public void logHours(int hours) {\n        this.hours += hours;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.hourlyRate * this.hours;\n    }\n}\n// ==== Payroll.java ====\nimport java.util.ArrayList;\n\npublic class Payroll {\n    private ArrayList<Employee> employees;\n\n    public Payroll() {\n        this.employees = new ArrayList<>();\n    }\n\n    public void add(Employee employee) {\n        this.employees.add(employee);\n    }\n\n    public int total() {\n        int total = 0;\n        for (Employee employee : this.employees) {\n            total += employee.monthlyPay();\n        }\n        return total;\n    }\n\n    public void printSlips() {\n        for (Employee employee : this.employees) {\n            System.out.println(employee);\n        }\n        System.out.println(\"Total: \" + this.total());\n    }\n}\n```\n\n```output\nRosa: 4500\nSam: 2530\nOmar: 5100\nTotal: 12130\n```\n\n- Payroll knows only Employee. `add` takes an Employee, the list is an `ArrayList<Employee>`, and `total` calls `monthlyPay()` on each. It never asks which kind of employee it has.\n- Each kind brings its own `monthlyPay()`. Employee's `toString` calls `this.monthlyPay()`, and the object's own version runs, so each slip shows the right pay.\n- `sam` is an HourlyEmployee variable, because `main` needs `logHours`, which only hourly employees have. Handed to `add`, the same object is just an Employee to the payroll. Each part of the program uses the type that has what it needs, and no more.\n- `monthlyPay()` is abstract, since there's no pay for \"an employee\" in general. javac won't compile a class that extends Employee without one, unless that class is abstract too. A class further down, such as one that extends SalariedEmployee, can use the version it inherits.\n\n### A new kind of employee\n\nThe company takes on interns, who get a fixed 900 a month. That's one new class:\n\n```java\npublic class Intern extends Employee {\n    public Intern(String name) {\n        super(name);\n    }\n\n    @Override\n    public int monthlyPay() {\n        return 900;\n    }\n}\n```\n\nAnd that's the whole change. Payroll isn't touched: with `payroll.add(new Intern(\"Kai\"));` in `main`, the slips get a line `Kai: 900`, and the total grows by 900. Payroll was written before interns existed, and it works with them, as it will with every class that extends Employee.\n\n### Without polymorphism\n\nCompare a Payroll that works out the pay itself with `instanceof` (with getters for each kind's numbers):\n\n```java\npublic int total() {\n    int total = 0;\n    for (Employee employee : this.employees) {\n        if (employee instanceof SalariedEmployee) {\n            SalariedEmployee salaried = (SalariedEmployee) employee;\n            total += salaried.getYearlySalary() / 12;\n        } else if (employee instanceof HourlyEmployee) {\n            HourlyEmployee hourly = (HourlyEmployee) employee;\n            total += hourly.getHourlyRate() * hourly.getHours();\n        }\n    }\n    return total;\n}\n```\n\n- The pay rules have moved out of the classes they belong to, into Payroll.\n- Interns need another `else if`, here and in every other method that works out pay. Forget one, and interns quietly get 0.\n- With a `monthlyPay()` in each class, each rule lives next to its own data, and a new kind of employee is one new class.\n\n### A list of an interface type\n\nThe general type can just as well be an interface. A notification service sends emails, text messages and app alerts. They have nothing in common but being sent, so they share an interface, and no superclass other than Object:\n\n```java\npublic interface Notification {\n    String deliver();\n}\n```\n\nAn `ArrayList<Notification>` can hold all of them, and a loop can call `deliver()` on each, which returns the message as that kind sends it. The last task of this step builds that.\n","task":"The company also has salespeople. A salesperson gets 1800 a month, plus 5 percent of the month's sales, rounded down as integer division does. `Employee.java`, `SalariedEmployee.java` and `Payroll.java` are the lesson's. In `SalesEmployee.java`, write the class `SalesEmployee`, which extends Employee, with:\n\n- a constructor `SalesEmployee(String name)`; a new salesperson has sold nothing yet\n- `recordSale(int amount)`, which adds a sale to the month's sales\n- `monthlyPay()`, overridden to return 1800 plus 5 percent of the sales\n\nDon't change Payroll: it already works with every kind of employee. The check runs:\n\n```java\nPayroll payroll = new Payroll();\nSalesEmployee lin = new SalesEmployee(\"Lin\");\nlin.recordSale(12000);\nlin.recordSale(4500);\npayroll.add(new SalariedEmployee(\"Rosa\", 54000));\npayroll.add(lin);\npayroll.printSlips();\n```\n\nand expects:\n\n```\nRosa: 4500\nLin: 2625\nTotal: 7125\n```\n","kind":"code","seed":"// ==== SalesEmployee.java ====\npublic class SalesEmployee {\n\n}\n\n// ==== Employee.java ====\npublic abstract class Employee {\n    private String name;\n\n    public Employee(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public abstract int monthlyPay();\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.monthlyPay();\n    }\n}\n\n// ==== SalariedEmployee.java ====\npublic class SalariedEmployee extends Employee {\n    private int yearlySalary;\n\n    public SalariedEmployee(String name, int yearlySalary) {\n        super(name);\n        this.yearlySalary = yearlySalary;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.yearlySalary / 12;\n    }\n}\n\n// ==== Payroll.java ====\nimport java.util.ArrayList;\n\npublic class Payroll {\n    private ArrayList<Employee> employees;\n\n    public Payroll() {\n        this.employees = new ArrayList<>();\n    }\n\n    public void add(Employee employee) {\n        this.employees.add(employee);\n    }\n\n    public int total() {\n        int total = 0;\n        for (Employee employee : this.employees) {\n            total += employee.monthlyPay();\n        }\n        return total;\n    }\n\n    public void printSlips() {\n        for (Employee employee : this.employees) {\n            System.out.println(employee);\n        }\n        System.out.println(\"Total: \" + this.total());\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Payroll payroll = new Payroll();\n        SalesEmployee lin = new SalesEmployee(\"Lin\");\n        lin.recordSale(12000);\n        lin.recordSale(4500);\n        payroll.add(new SalariedEmployee(\"Rosa\", 54000));\n        payroll.add(lin);\n        payroll.printSlips();\n    }\n}\n","solution":"// ==== SalesEmployee.java ====\npublic class SalesEmployee extends Employee {\n    private int sales;\n\n    public SalesEmployee(String name) {\n        super(name);\n        this.sales = 0;\n    }\n\n    public void recordSale(int amount) {\n        this.sales += amount;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return 1800 + this.sales * 5 / 100;\n    }\n}\n\n// ==== Employee.java ====\npublic abstract class Employee {\n    private String name;\n\n    public Employee(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public abstract int monthlyPay();\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.monthlyPay();\n    }\n}\n\n// ==== SalariedEmployee.java ====\npublic class SalariedEmployee extends Employee {\n    private int yearlySalary;\n\n    public SalariedEmployee(String name, int yearlySalary) {\n        super(name);\n        this.yearlySalary = yearlySalary;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.yearlySalary / 12;\n    }\n}\n\n// ==== Payroll.java ====\nimport java.util.ArrayList;\n\npublic class Payroll {\n    private ArrayList<Employee> employees;\n\n    public Payroll() {\n        this.employees = new ArrayList<>();\n    }\n\n    public void add(Employee employee) {\n        this.employees.add(employee);\n    }\n\n    public int total() {\n        int total = 0;\n        for (Employee employee : this.employees) {\n            total += employee.monthlyPay();\n        }\n        return total;\n    }\n\n    public void printSlips() {\n        for (Employee employee : this.employees) {\n            System.out.println(employee);\n        }\n        System.out.println(\"Total: \" + this.total());\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Payroll payroll = new Payroll();\n        SalesEmployee lin = new SalesEmployee(\"Lin\");\n        lin.recordSale(12000);\n        lin.recordSale(4500);\n        payroll.add(new SalariedEmployee(\"Rosa\", 54000));\n        payroll.add(lin);\n        payroll.printSlips();\n    }\n}\n","hints":["Start like HourlyEmployee: `public class SalesEmployee extends Employee {`, a private `int sales`, and a constructor that hands the name on with `super(name);` and sets the sales to 0. `recordSale` adds the amount to the sales.","Override `monthlyPay()` with `@Override`, and return `1800 + this.sales * 5 / 100`. Multiply before dividing: `this.sales / 100 * 5` would lose the part under 100."],"tests":[{"name":"Test 1","stdin":"","call":"Payroll payroll = new Payroll();\nSalesEmployee lin = new SalesEmployee(\"Lin\");\nlin.recordSale(12000);\nlin.recordSale(4500);\npayroll.add(new SalariedEmployee(\"Rosa\", 54000));\npayroll.add(lin);\npayroll.printSlips();\n","expect":"Rosa: 4500\nLin: 2625\nTotal: 7125","hidden":false},{"name":"Test 2","stdin":"","call":"SalesEmployee ana = new SalesEmployee(\"Ana\");\nSystem.out.println(ana.monthlyPay());\nana.recordSale(99);\nSystem.out.println(ana);\nana.recordSale(1);\nEmployee employee = ana;\nSystem.out.println(employee.monthlyPay() + \" \" + employee.getName());\n","expect":"1800\nAna: 1804\n1805 Ana","hidden":true},{"name":"Test 3","stdin":"","call":"Payroll payroll = new Payroll();\nSalesEmployee bo = new SalesEmployee(\"Bo\");\nSalesEmployee cy = new SalesEmployee(\"Cy\");\npayroll.add(bo);\npayroll.add(cy);\nbo.recordSale(20000);\ncy.recordSale(1000);\ncy.recordSale(3050);\nSystem.out.println(payroll.total());\npayroll.printSlips();\n","expect":"4802\nBo: 2800\nCy: 2002\nTotal: 4802","hidden":true}],"require":[{"pattern":"\\bclass\\s+SalesEmployee\\s+extends\\s+Employee\\b","message":"Write the header as `public class SalesEmployee extends Employee`."}],"forbid":[],"more":[{"task":"A manager is a salaried employee with 400 a month on top of the salary. Sam logs his hours after he's been added to the list. What does this program print?\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Employee> staff = new ArrayList<>();\n        HourlyEmployee sam = new HourlyEmployee(\"Sam\", 20);\n        staff.add(sam);\n        staff.add(new Manager(\"Ines\", 60000));\n        staff.add(new SalariedEmployee(\"Rosa\", 48000));\n        sam.logHours(50);\n\n        int total = 0;\n        for (Employee employee : staff) {\n            total += employee.monthlyPay();\n        }\n        System.out.println(staff.get(0));\n        System.out.println(staff.get(1));\n        System.out.println(total);\n    }\n}\n// ==== Employee.java ====\npublic abstract class Employee {\n    private String name;\n\n    public Employee(String name) {\n        this.name = name;\n    }\n\n    public abstract int monthlyPay();\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.monthlyPay();\n    }\n}\n// ==== SalariedEmployee.java ====\npublic class SalariedEmployee extends Employee {\n    private int yearlySalary;\n\n    public SalariedEmployee(String name, int yearlySalary) {\n        super(name);\n        this.yearlySalary = yearlySalary;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.yearlySalary / 12;\n    }\n}\n// ==== Manager.java ====\npublic class Manager extends SalariedEmployee {\n    public Manager(String name, int yearlySalary) {\n        super(name, yearlySalary);\n    }\n\n    @Override\n    public int monthlyPay() {\n        return super.monthlyPay() + 400;\n    }\n}\n// ==== HourlyEmployee.java ====\npublic class HourlyEmployee extends Employee {\n    private int hourlyRate;\n    private int hours;\n\n    public HourlyEmployee(String name, int hourlyRate) {\n        super(name);\n        this.hourlyRate = hourlyRate;\n        this.hours = 0;\n    }\n\n    public void logHours(int hours) {\n        this.hours += hours;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.hourlyRate * this.hours;\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Employee> staff = new ArrayList<>();\n        HourlyEmployee sam = new HourlyEmployee(\"Sam\", 20);\n        staff.add(sam);\n        staff.add(new Manager(\"Ines\", 60000));\n        staff.add(new SalariedEmployee(\"Rosa\", 48000));\n        sam.logHours(50);\n\n        int total = 0;\n        for (Employee employee : staff) {\n            total += employee.monthlyPay();\n        }\n        System.out.println(staff.get(0));\n        System.out.println(staff.get(1));\n        System.out.println(total);\n    }\n}\n// ==== Employee.java ====\npublic abstract class Employee {\n    private String name;\n\n    public Employee(String name) {\n        this.name = name;\n    }\n\n    public abstract int monthlyPay();\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.monthlyPay();\n    }\n}\n// ==== SalariedEmployee.java ====\npublic class SalariedEmployee extends Employee {\n    private int yearlySalary;\n\n    public SalariedEmployee(String name, int yearlySalary) {\n        super(name);\n        this.yearlySalary = yearlySalary;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.yearlySalary / 12;\n    }\n}\n// ==== Manager.java ====\npublic class Manager extends SalariedEmployee {\n    public Manager(String name, int yearlySalary) {\n        super(name, yearlySalary);\n    }\n\n    @Override\n    public int monthlyPay() {\n        return super.monthlyPay() + 400;\n    }\n}\n// ==== HourlyEmployee.java ====\npublic class HourlyEmployee extends Employee {\n    private int hourlyRate;\n    private int hours;\n\n    public HourlyEmployee(String name, int hourlyRate) {\n        super(name);\n        this.hourlyRate = hourlyRate;\n        this.hours = 0;\n    }\n\n    public void logHours(int hours) {\n        this.hours += hours;\n    }\n\n    @Override\n    public int monthlyPay() {\n        return this.hourlyRate * this.hours;\n    }\n}\n","hints":["The list holds a reference to the object `sam` refers to, not a copy, so the 50 hours logged afterwards count in the list too.","Ines is a Manager: her `monthlyPay()` runs SalariedEmployee's version with `super.monthlyPay()`, a twelfth of 60000, and adds 400. Rosa gets a twelfth of 48000."],"tests":[{"name":"Output","stdin":"","expect":"Sam: 1000\nInes: 5400\n10400","hidden":false}],"require":[],"forbid":[],"lines":["Sam: 1000","Ines: 5400","10400"]},{"task":"A notification service sends three kinds of message. `Notification.java` is the interface from the lesson, with one method, `String deliver()`, which returns the message as it's sent. `Email.java` and `PushAlert.java` are ready. Write:\n\n- In `Sms.java`, the class `Sms`, which implements Notification. Its constructor is `Sms(String phone, String text)`, and `deliver()` returns `SMS to `, the phone number, `: ` and the text. A text message has little room, so a text longer than 20 characters is cut to its first 20 characters, followed by `...`.\n- In `Main.java`, the method `sendAll(ArrayList<Notification> outbox)`, which prints what each notification delivers, one per line, and then how many were sent, like `4 sent`.\n\n`sendAll` shouldn't care which kind each notification is. The check runs:\n\n```java\nArrayList<Notification> outbox = new ArrayList<>();\noutbox.add(new Email(\"ada@example.com\", \"Your invoice\"));\noutbox.add(new Sms(\"555-0142\", \"Your code is 4417\"));\noutbox.add(new PushAlert(\"Weather\", \"Rain at 3 pm\"));\noutbox.add(new Sms(\"555-0199\", \"Table for 4 is ready at the front desk\"));\nsendAll(outbox);\n```\n\nand expects:\n\n```\nEmail to ada@example.com: Your invoice\nSMS to 555-0142: Your code is 4417\n[Weather] Rain at 3 pm\nSMS to 555-0199: Table for 4 is ready...\n4 sent\n```\n","kind":"code","seed":"// ==== Sms.java ====\npublic class Sms {\n\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Notification> outbox = new ArrayList<>();\n        outbox.add(new Email(\"ada@example.com\", \"Your invoice\"));\n        outbox.add(new Sms(\"555-0142\", \"Your code is 4417\"));\n        outbox.add(new PushAlert(\"Weather\", \"Rain at 3 pm\"));\n        outbox.add(new Sms(\"555-0199\", \"Table for 4 is ready at the front desk\"));\n        sendAll(outbox);\n    }\n\n    // Write the method sendAll here.\n}\n\n// ==== Notification.java ====\npublic interface Notification {\n    String deliver();\n}\n\n// ==== Email.java ====\npublic class Email implements Notification {\n    private String address;\n    private String subject;\n\n    public Email(String address, String subject) {\n        this.address = address;\n        this.subject = subject;\n    }\n\n    @Override\n    public String deliver() {\n        return \"Email to \" + this.address + \": \" + this.subject;\n    }\n}\n\n// ==== PushAlert.java ====\npublic class PushAlert implements Notification {\n    private String app;\n    private String text;\n\n    public PushAlert(String app, String text) {\n        this.app = app;\n        this.text = text;\n    }\n\n    @Override\n    public String deliver() {\n        return \"[\" + this.app + \"] \" + this.text;\n    }\n}\n","solution":"// ==== Sms.java ====\npublic class Sms implements Notification {\n    private String phone;\n    private String text;\n\n    public Sms(String phone, String text) {\n        this.phone = phone;\n        this.text = text;\n    }\n\n    @Override\n    public String deliver() {\n        String shown = this.text;\n        if (shown.length() > 20) {\n            shown = shown.substring(0, 20) + \"...\";\n        }\n        return \"SMS to \" + this.phone + \": \" + shown;\n    }\n}\n\n// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Notification> outbox = new ArrayList<>();\n        outbox.add(new Email(\"ada@example.com\", \"Your invoice\"));\n        outbox.add(new Sms(\"555-0142\", \"Your code is 4417\"));\n        outbox.add(new PushAlert(\"Weather\", \"Rain at 3 pm\"));\n        outbox.add(new Sms(\"555-0199\", \"Table for 4 is ready at the front desk\"));\n        sendAll(outbox);\n    }\n\n    public static void sendAll(ArrayList<Notification> outbox) {\n        for (Notification notification : outbox) {\n            System.out.println(notification.deliver());\n        }\n        System.out.println(outbox.size() + \" sent\");\n    }\n}\n\n// ==== Notification.java ====\npublic interface Notification {\n    String deliver();\n}\n\n// ==== Email.java ====\npublic class Email implements Notification {\n    private String address;\n    private String subject;\n\n    public Email(String address, String subject) {\n        this.address = address;\n        this.subject = subject;\n    }\n\n    @Override\n    public String deliver() {\n        return \"Email to \" + this.address + \": \" + this.subject;\n    }\n}\n\n// ==== PushAlert.java ====\npublic class PushAlert implements Notification {\n    private String app;\n    private String text;\n\n    public PushAlert(String app, String text) {\n        this.app = app;\n        this.text = text;\n    }\n\n    @Override\n    public String deliver() {\n        return \"[\" + this.app + \"] \" + this.text;\n    }\n}\n","hints":["Sms starts `public class Sms implements Notification {`, keeps the phone and the text in private variables, and writes `deliver()` with `@Override`. When `text.length() > 20`, use `text.substring(0, 20) + \"...\"` in place of the text.","`sendAll` goes through the outbox with a for-each loop over `Notification`s, prints `notification.deliver()` for each, and after the loop prints `outbox.size() + \" sent\"`. Each object's own `deliver()` does the rest."],"tests":[{"name":"Test 1","stdin":"","call":"ArrayList<Notification> outbox = new ArrayList<>();\noutbox.add(new Email(\"ada@example.com\", \"Your invoice\"));\noutbox.add(new Sms(\"555-0142\", \"Your code is 4417\"));\noutbox.add(new PushAlert(\"Weather\", \"Rain at 3 pm\"));\noutbox.add(new Sms(\"555-0199\", \"Table for 4 is ready at the front desk\"));\nsendAll(outbox);\n","expect":"Email to ada@example.com: Your invoice\nSMS to 555-0142: Your code is 4417\n[Weather] Rain at 3 pm\nSMS to 555-0199: Table for 4 is ready...\n4 sent","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<Notification> outbox = new ArrayList<>();\noutbox.add(new Sms(\"555-0100\", \"12345678901234567890\"));\noutbox.add(new Sms(\"555-0101\", \"123456789012345678901\"));\noutbox.add(new Sms(\"555-0102\", \"Hi\"));\nsendAll(outbox);\n","expect":"SMS to 555-0100: 12345678901234567890\nSMS to 555-0101: 12345678901234567890...\nSMS to 555-0102: Hi\n3 sent","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Notification> outbox = new ArrayList<>();\nsendAll(outbox);\noutbox.add(new PushAlert(\"Bank\", \"Card used\"));\nNotification sms = new Sms(\"555-0177\", \"Meeting moved to 4 pm tomorrow\");\noutbox.add(sms);\nsendAll(outbox);\nSystem.out.println(sms.deliver().length());\n","expect":"0 sent\n[Bank] Card used\nSMS to 555-0177: Meeting moved to 4 p...\n2 sent\n40","hidden":true}],"require":[{"pattern":"\\bclass\\s+Sms\\s+implements\\s+Notification\\b","message":"Write the header as `public class Sms implements Notification`."},{"pattern":"\\bpublic\\s+static\\s+void\\s+sendAll\\s*\\(\\s*ArrayList\\s*<\\s*Notification\\s*>\\s+\\w+\\s*\\)","message":"Write the method as `public static void sendAll(ArrayList<Notification> outbox)`."}],"forbid":[{"pattern":"\\binstanceof\\b","message":"`sendAll` doesn't need to know the kinds: each notification's own `deliver()` does its part."}]}]}