Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS 112 Introduction to Programming Critters, Polymorphism Yang (Richard) Yang Computer Science Department Yale University 208A Watson, Phone: 432-6400.

Similar presentations


Presentation on theme: "CS 112 Introduction to Programming Critters, Polymorphism Yang (Richard) Yang Computer Science Department Yale University 208A Watson, Phone: 432-6400."— Presentation transcript:

1 CS 112 Introduction to Programming Critters, Polymorphism Yang (Richard) Yang Computer Science Department Yale University 208A Watson, Phone: 432-6400 Email: yry@cs.yale.edu

2 2 Admin  Project proposal due tomorrow

3 3 Recap: Inheritance and Method Overriding  A child class can (have the option to) override the definition of an inherited method in favor of its own  Good overriding design: if the child’s behavior is derived from the parent class, use the parent’s method as a base public class Marketer extends Employee { … @Override // override and invoke the parent’s version public double pay() { return super.pay() * 1.2; } … }

4 4 Recap: Inheritance and Field/Method Access  A child class cannot access private fields/methods of the parent class m To achieve the encapsulation of the parent class  Two approaches to access a field/method defined in parent class  Parent class defines it as public  Parent class defines it as protected

5 Recap: Critters and Event-Driven Programming  Key concepts: m The simulator is in control, NOT an animal. An animal must keep state (as fields) so that it can make a single move, and know what moves to make later. We say that event-driven programming focuses on writing the callback functions of objects % Next move?

6 Recap: Cougar  Write a critter class Cougar MethodBehavior constructor public Cougar() eat Always eats. fight Always roars. getColor Blue if the Cougar has never fought; red if he has. getMove Walks west until he finds food; then walks east until he finds food; then goes west and repeats. toString"C"

7 Recap: getMove for Cougar  State machine  How to remember the state?  a boolean instance variable: boolean west  What is initial state and where to set it?  In constructor: west = true;  Who/when updates the state?  In eat(): reverse state 7 Move West Move East eat()

8 getColor for Cougar  State machine  How to remember the state?  A boolean instance variable: boolean fought  What is initial state and where to set it?  In constructor: fought = false;  Who/when updates the state?  In fight(): fought = true 8 ! Has fought Has fought fight() Blue if the Cougar has never fought; red if he has.

9 Critter : Snake MethodBehavior constructor public Snake() eat Never eats fight random pounce or roar getColor Color(20, 50, 128) getMove 1 E, 1 S; 2 W, 1 S; 3 E, 1 S; 4 W, 1 S; 5 E,... toString"S"

10 Determining necessary fields  Information required to decide what move to make? m Length of current cycle m Number of moves made in current cycle m Direction to go

11 Non-EDP Version A non-event driven version cycleLength = 1; while (true) { steps = 0; while (steps < cycleLength) if cycleLength % 2 == 1 go East else go West steps ++; go South cycleLength ++ }

12 Non-EDP-> EDP: Guarding Condition 12 steps < cycleLength if (cycleLength % 2 == 1) go East else go West steps++; steps == cycleLength go South cycleLength ++ steps=0; A non-event driven version cycleLength = 1; steps = 0; while (true) { while (steps < cycleLength) if cycleLength % 2 == 1 go East else go West steps ++; // invariant? go South cycleLength ++; steps = 0; }

13 Snake solution import java.awt.*; // for Color public class Snake extends Critter { private int cycleLength; // # steps in curr. Horiz. cycle private int steps; // # of cycle's steps already taken public Snake() { cycleLength = 1; steps = 0; } public Direction getMove() { if (steps < cycleLength) { steps++; if (cycleLength % 2 == 1) { return Direction.EAST; } else { return Direction.WEST; } } else { steps = 0; cycleLength ++; return Direction.SOUTH; } public String toString() { return "S"; } steps < cycleLength if (cycleLength % 2 == 1) go East else go West steps++; steps == cycleLength Go South cycleLength ++ steps=0;

14 Comment: States  Counting is helpful: m How many total moves has this animal made? m How many times has it eaten? Fought?  Remembering recent actions in fields may be helpful: m Which direction did the animal move last? How many times has it moved that way? m Did the animal eat the last time it was asked? m How many steps has the animal taken since last eating? m How many fights has the animal been in since last eating?

15 Testing critters  Focus on one specific critter of one specific type m Only spawn 1 of each animal, for debugging  Make sure your fields update properly  Use println statements to see field values  Look at the behavior one step at a time m Use "Tick" rather than "Go"

16 Designing Bulldog  Be open minded  Think about strategies, e.g., m How much state do your bulldogs keep and probe state? m When do your bulldogs eat/mate? m Is there an “optimal” fight strategy for a specific type of opponent? m Do your bulldogs play disguise? m Does your strategy change with time? m Do your bulldogs coordinate their behaviors to form some kind of patterns? 16

17 Coordination 17 https://www.youtube.com/watch?v=_sUeGC-8dyk

18 Coordination 18

19 Critter exercise : Hipster  A group of hipster critters want to hangout together  Each hipster can suddenly become inspired and choose a random board location called an edgy bar  A hipster go north until reaches edgy bar’s horizontal, then east until reaching the bar

20 Solution 1 (See Hipster.java) public class Hipster extends Critter { private Random rand; private int edgyBarX, edgyBarY; private int nextT, t; private final int FLASH_INTERVAL = 200; public Hipster() { rand = new Random(); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } public Direction getMove(String[][] grid) { t ++; if (t == nextT) { edgyBarX = rand.nextInt( getWidth() ); edgyBarY = rand.nextInt( getHeight() ); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } if (getY() != edgyBarY) { return Direction.NORTH; } else if (getX() != edgyBarX) { return Direction.EAST; } else { return Direction.CENTER; } public String toString() { return "H(" + edgyBarX + "," +edgyBarY + ")”; }

21 Solution 1 (See Hipster.java) public class Hipster extends Critter { private Random rand; private int edgyBarX, edgyBarY; private int nextT, t; private final int FLASH_INTERVAL = 200; public Hipster() { rand = new Random(); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } public Direction getMove(String[][] grid) { t ++; if (t == nextT) { edgyBarX = rand.nextInt( getWidth() ); edgyBarY = rand.nextInt( getHeight() ); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } if (getY() != edgyBarY) { return Direction.NORTH; } else if (getX() != edgyBarX) { return Direction.EAST; } else { return Direction.CENTER; } public String toString() { return "H(" + edgyBarX + "," +edgyBarY + ")”; }  Problem: Each hipster goes to a different bar. We want all hipsters to share the same bar location.

22 Solution 1 (See Hipster.java) public class Hipster extends Critter { private Random rand; private static int edgyBarX, edgyBarY; private int nextT, t; private final int FLASH_INTERVAL = 200; public Hipster() { rand = new Random(); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } public Direction getMove(String[][] grid) { t ++; if (t == nextT) { edgyBarX = rand.nextInt( getWidth() ); edgyBarY = rand.nextInt( getHeight() ); t = 0; nextT = rand.nextInt(FLASH_INTERVAL); } if (getY() != edgyBarY) { return Direction.NORTH; } else if (getX() != edgyBarX) { return Direction.EAST; } else { return Direction.CENTER; } public String toString() { return "H(" + edgyBarX + "," +edgyBarY + ")”; }

23 Recall: Static members  static: Part of a class, rather than part of an object. m Object classes can have static methods and fields. m Not copied into each object; shared by all objects of that class. class state: private static int staticFieldA private static String staticFieldB behavior: public static void someStaticMethodC() public static void someStaticMethodD() object #1 state: int field1 double field2 behavior: public void method3() public int method4() public void method5() object #2 state: int field1 double field2 behavior: public void method3() public int method4() public void method5() object #3 state: int field1 double field2 behavior: public void method3() public int method4() public void method5()

24 Accessing static fields  From inside the class where the field was declared: fieldName // get the value fieldName = value ; // set the value  From another class (if the field is public ): ClassName. fieldName // get the value ClassName. fieldName = value ; // set the value  generally static fields are not public unless they are final

25 25 Example  We want to automatically assign a unique, increasing employee ID for each Employee object (e.g., Secretary, Marketer, Lawyer) that we create

26 Employee with Auto-gen ID public class Employee { private String name; private int empID; private static int nextEmpID = 1000; public Employee(String name) { this.name = name; empID = nextEmpID; nextEmpID++; } public static int nextEmpID() { return nextEmpID; } … } public class Firm { public static void main(String[] args) { Lawyer larry = new Lawyer(“Larry"); Marketer mike = new Marketer("Mike"); Lawyer lynn = new Lawyer(”Lynn"); }

27 27 Example: The Employee Objects Employee.nextEmpID 1000 public class Employee { private String name; private int empID; private static int nextEmpID = 1000; public Employee(String name) { this.name = name; emplID = nextEmpID; nextEmpID++; } … }

28 28 Example: The Employee Objects larry: Lawyer name = “Larry” empID = 1000; Lawyer larry = new Lawyer("Larry"); Employee.nextEmpID 1000 1001 public class Employee { private String name; private int empID; private static int nextEmpID = 1000; public Employee(String name) { this.name = name; emplID = nextEmpID; nextEmpID++; } … }

29 29 Example: The Employee Objects larry: Lawyer name = “Larry” empID = 1000; mike: Marketer name = “Mike” empID = 1001; Marketer mike = new Marketer("Mike"); Employee.nextEmpID 1001 1002 public class Employee { private String name; private int empID; private static int nextEmpID = 1000; public Employee(String name) { this.name = name; emplID = nextEmpID; nextEmpID++; } … }

30 Back to Hipster public class Hipster extends Critter { Random rand; private static int edgyBarX, edgyBarY; private int nextT, t; public Hipster() { rand = new Random(); t = 0; nextT = rand.nextInt(200); } public Direction getMove(String[][] grid) { t ++; if (t == nextT) { edgyBarX = rand.nextInt(60); edgyBarY = rand.nextInt(50); t = 0; nextT = rand.nextInt(200); } if (getY() != edgyBarY) { return Direction.NORTH; } else if (getX() != edgyBarX) { return Direction.EAST; } else { return Direction.CENTER; } public String toString() { return "H(" + edgyBarX + "," +edgyBarY + ")”; }

31 (offline) Exercise  Design a type of critters that can conduct formation, e.g., move around a circle with equal distance (enough to earn you full 20 points of Part 2/PS8)

32 Comment: PS8 Development Strategy  Do one species at a time m in ABC order from easier to harder m debug printlns  Simulator helps you debug m smaller width/height m fewer animals m "Tick" instead of "Go" m "Debug" checkbox m drag/drop to move animals

33 33 Outline  Admin and recap  Critters and objects coordination  Polymorphism

34 Motivation  The controller implemented in CritterMain.java works on all critters objects  How does one write such a highly reusable program? % Next move?

35 What is Polymorphism?  polymorphism: Ability for the same code to be used with different types of objects and behave differently according to the types of objects.  The foundation of polymorphism is dynamic typing: the method invoked is always determined by the object, not the class.

36 36 Recap: Reference Variables  Interaction with an object occurs through object reference variables  An object reference variable holds the reference (address, the location) of an object ChessPiece bishop1 = new ChessPiece(); bishop1

37 37 Recap: Object Reference Variable  Object reference variable assignment copies address, creating aliases bishop2 = bishop1; Before bishop1bishop2 After bishop1bishop2

38 Requirements on Polymorphic Code X x; … x.method(); … x.method(); x can point to different types of objects method() exists in these different obejcts method() exists in these different objects method() exists in these different obejcts method() behaves differently

39 Polymorphism through Inheritance  Same reference points to different types of objects  A variable of type T can hold an object of class T or descendent of T, e.g., Employee emp = new Employee(“Ed”); emp = new Lawyer(“Larry”); emp = new LegalSecretary(“Lisa”);  The method used exists in all the objects m If the method is defined in the base class  The method may behave differently m The child class can override the method

40 Polymorphism Example Employee emp; // base type emp = new Lawyer("Larry"); System.out.println ( emp.vacationDays() ); // OUTPUT: 15 System.out.println ( emp.vacationForm() ); // OUTPUT: pink emp = new LegalSecretary(“Lisa"); System.out.println ( emp.vacationDays() ); // OUTPUT: 10 System.out.println ( emp.vacationForm() ); // OUTPUT: yellow 40

41 Polymorphism Example 41 Employee emp Reference variable type Object type: Lawyer Object type: Secretary emp.vacationDays() // 15 emp.vacationDays() // 10

42 Polymorphism through Inheritance  You can call any methods defined in the based class T (e.g., Employee ) class on polymorphic reference of type T (e.g., emp )  When you invoke a method through a polymorphic reference variable, it is the type of the object being referenced, not the reference type, that determines which method is invoked.  Careful use of polymorphic references can lead to elegant, robust software designs

43 Polymorphism Example: Method  Define a method that can apply to all objects of a base type its derived types.  This is how print in PrintStream is defined: void print(Object obj) { // all objects have the toString() method // convert to string and then output }

44 Polymorphic Method: Method w/ Polymorphic Reference as Parameter public class EmployeeMain { public static void main(String[] args) { Lawyer lisa = new Lawyer(); Secretary steve = new Secretary(); printInfo(lisa); printInfo(steve); } public static void printInfo(Employee empl) { System.out.println("salary: " + empl.pay()); System.out.println("v.days: " + empl.vacationDays()); System.out.println("v.form: " + empl.vacationForm()); System.out.println(); } OUTPUT:salary: 50000.0 v.days: 15v.days: 10 v.form: pinkv.form: yellow

45 Polymorphic Arrays  A common usage of polymorphism is to define an array of a base type, but different entries refer to different types of objects m To handle a heterogeneous population of objects with uniformity, achieving generic programming

46 Polymorphic Array index0123 Critter[] critters = { new Ant(), new Cougar(), new Snake(), new Bulldog() }; while (true) for (i=0; i<critters.length; i++) pos = critters[i].getMove(); disp = critters[i].toString(); draw disp at pos Not dependent on any specific critters but only the generic Critter concept

47 Polymorphic Array public class Staff { private Employee[] staffList; public Staff() { staffList = new Employee[4]; staffList[0] = new Lawyer("Lisa"); staffList[1] = new Secretary("Sally"); staffList[2] = new Marketer("Mike"); staffList[3] = new LegalSecretary("Lynne"); } public void payday() { for (int count = 0; count < staffList.length; count++) { System.out.printf("%-10s:", staffList[count].name()); System.out.printf("$%.2f\n", staffList[count].pay()); System.out.println("-----------------------------------"); } Works on any mix of Employee objects

48 Extending the Program: Hourly  Include a new type of secretary who works variable number of hours and is paid by the hours. 48

49 Extending the Program: Hourly Secretary public class Hourly extends Secretary { private double payRate; private int hours; public Hourly(String name, double payRate) super(name); this.payRate = payRate; hours = 0; } public void addHours(int hours) { this.hours += hours; } public int hours() { return hours; } public double pay() {return hours() * payRate;} } 49

50 Polymorphic Array Handles Changes public class Staff { private Employee[] staffList; public Staff() { staffList = new Employee[5]; staffList[0] = new Lawyer("Lisa"); staffList[1] = new Secretary("Sally"); staffList[2] = new Marketer("Mike"); staffList[3] = new LegalSecretary("Lynne"); Hourly holly = new Hourly(“Holly"); holly.addHours(10); staffList[4] = holly; } public void payday() { for (int count = 0; count < staffList.length; count++) { System.out.printf("%-10s:", staffList[count].name()); System.out.printf("$%.2f\n", staffList[count].pay()); System.out.println("-----------------------------------"); } No need to change the payday method at all.

51 51 Employee # name : String + toString() : String + pay() : double Hourly - payRate: double + pay() : double Lawyer + toString() : String + pay() : double Partner - bonus : double + awardBonus(bonus : double) : void + pay() : double Payroll + main (args : String[]) : void - staffList: staffMemeber[] Staff + payday() : void - staffList : Employee[] The pay-roll of a firm

52 52 Comment: Variable Type and Method  Through a given type of reference variable, we can invoke only the methods defined in that type Can we do the following statements: ed.pay(); ed.sue(); Employee ed = new Lawyer(“Larry”); class Employee{ public double pay() {…} } class Lawyer extends Employee { public void sue() {…} }

53 53 Comment: Variable Type and Method  We can “promote” an object back to its original type through an explicit narrowing cast: staffList = new Employee[5]; staffList[0] = new Lawyer("Lisa"); staffList[1] = new Secretary("Sally"); staffList[2] = new Marketer("Mike"); staffList[3] = new LegalSecretary("Lynne"); staffList[4] = new Hourly(“Holly"); Hourly holly = (Hourly)staffList[4]; holly.addHours (5); If the type of object referred to by staff[4] is not Hourly, program error.

54 Summary: Polymorphism  polymorphism: Ability for the same code to be used with different types of objects and behave differently with each.  System.out.println can print any type of object. Each one displays in its own way on the console.  CritterMain can interact with any type of critter. Each one moves, fights, etc. in its own way.

55 Backup Slides: Dynamic Binding 55

56 56 Example Setting  It turns out that the vacation bonus policy does not apply to secretaries: they get fixed 10 days vacation, not (10 + 2 * years)

57 57 Solution 1  We set all Secretaries to 0 years of service because they do not have vacation bonus public class Secretary extends Employee { public Secretary(String name, int years) { super(name, 0); } public void prepareDoc(String text) { System.out.println(“ Working on doc “ + text); }

58 58 Problem  Solution 1 is not good:  If we call getYears() on a Secretary object, we get 0 m What if we wanted to give other rewards to all employees based on years of service?

59 Idea: Separation public class Employee { private String name; private int years; public int vacationDays () { return 10 + 2 * years; } … } 59 Separate base days and bonus days to allow adaptation

60 Improved Employee code  Separate the standard 10 vacation days from those that are awarded based on seniority. public class Employee { private int years; public Employee(int initialYears) { years = initialYears; } public int getVacationDays() { return 10 + getSeniorityVacation(); } // vacation days given for each year in the company public int getSeniorityVacation() { return 2 * years; }... }  How does this help us improve the Secretary ?

61 Improved Secretary code  Secretary can override getSeniorityVacation. public class Secretary extends Employee { public Secretary(String name, int years) { super(name, years); } // Secretaries don't get a bonus for their years of service. public int getSeniorityVacation() { return 0; } public void prepareDoc(String text) { System.out.println(”Working on text: " + text); }

62 Example Client public class Firm { public static void main(String args) { Secretary seth = new Secretary(“Seth”, 10); int vacDays = seth.getVacationDays(); } // Defined in class Employee public int getVacationDays() { return 10 + getSeniorityVacation(); } // Defined in class Employee public int getSeniorityVacation() { return 2 * years; } // Defined in class Secretary public int getSeniorityVacation() { return 0; } Secretary obj’s method

63 Example Client public class Firm { public static void main(String args) { Lawyer larry = new Lawyer(“Larry”, 10); int vacDays = larry.getVacationDays(); } // Defined in class Employee public int getVacationDays() { return 10 + getSeniorityVacation(); } // Defined in class Employee public int getSeniorityVacation() { return 2 * years; }

64 Summary  The method invoked is always determined by the object, not the class. This is called dynamic binding, and it is extremely powerful!  Hence when a method in a base class invokes the name of another method defined in the base class, the real method invoked can be defined either in the base class, or a child class. // Defined in class Employee public int getVacationDays() { return 10 + getSeniorityVacation(); }


Download ppt "CS 112 Introduction to Programming Critters, Polymorphism Yang (Richard) Yang Computer Science Department Yale University 208A Watson, Phone: 432-6400."

Similar presentations


Ads by Google