Lecture 6: Advanced OOP. Overview The switch statement Enumerations Subclasses Overloading vs....

50
CSCI1227 Computer Programming and Problem Solving Lecture 6: Advanced OOP

Transcript of Lecture 6: Advanced OOP. Overview The switch statement Enumerations Subclasses Overloading vs....

Slide 1

CSCI1227Computer Programming andProblem Solving Lecture 6: Advanced OOPOverviewThe switch statementEnumerationsSubclassesOverloading vs. Overriding

ExerciseCreate an ADT called flag. A flag has two properties:A picture that is put on it (represented by a String containing the file containing the image), andA position (either up or down its flying or its not).The image of the flag is constant and never changes, but the flag can be raised and lowered.Don't worry about how the flag is going to be displayed just assume that someone else is going to handle that part later.

Solutionpublic class flag{ // Hidden instance data private boolean raised; private final String image; // Constructor public flag (String i) { raised = false; image = i; } // Public interface methods public boolean isFlying() { return (raised); } public void raise () { raised = true; } public void lower () { raised = false; }} // end class flagif-else chainsWe often see long chains of if-else statementsSome of these chains test the same variable over and over This behaviour happens so often that we "break" the rules for proper indentation when we do itThere is actually a special construct that we can use for this situation the switch statementExample: A chain of if'spublic static String expandMonth(String m) { if (m.equals("Jan")) { return ("January"); } else { if (m.equals("Feb")) { return ("February"); } else { if (m.equals("Mar")) { return ("March"); } else { ... etc ... } } }} // end expandMonth()Example: Alternative Formatpublic static String expandMonth(String m) { if (m.equals("Jan")) { return ("January"); } else if (m.equals("Feb")) { return ("February"); } else if (m.equals("Mar")) { return ("March"); } else if (m.equals("Apr")) { ... etc .. }} // end expandMonth()

We deleted the curly braces on all the else clauses since they only contain a single ifswitch (Text 3.3)Syntax: switch (expression) { cases }The expression must evaluate to an integer type, character, enumeration , or String (v7 on)cases have the format: case value: actionsThe values can be in any order, you can skip valueseach action ends with the statement break; unless you want to "fall through" and execute the actions for the next caseA default: case can be specified for when no other case matchesExample: switchpublic static String expandMonth(String m) { switch (m) { case "Jan": // Falls through case "jan": // Falls through case "Ja": return ("January"); break; // Not really needed, return causes exit from method case "Mar": return ("March"); break; // Not really needed, just for good form and clarity case "Feb": return ("February"); break; default: return ("April-December"); }} // end expandMonth()Patterns = Loops!public static final String[] months = { "January", "February", "March" ... etc ...};

public static String expandMonth(String m) { for (int i = 0; i < months.length; i++) { if (m.equals(months[i].substring(0,3))) return (months[i]); }} // end expandMonth() Data PatternsPatterns are an important element of programmingData can often be grouped according to meaningful concepts "Monday", "Tuesday", "Wednesday", ..."Heart", "Club", "Diamond", "Spade""Male", "Female""North", "South", "East", "West""Argonauts", "Alouettes", "Lions", "Eskimos", ...While we can encode these data items with strings, there is a better way -- enumerationsEnumerations (Text 3.3)Create a new class/typeenum suit { heart, club, diamond, spade }Note: Does NOT end with a semi-colonHave special properties - not a regular classThere is one instance of the type/class for each value (i.e., the instances are static!)We can create variables and use these instancessuit su = suit.heart; Since heart is static, we precede it with the class/type nameExtending the Flagenum pole { lowered, halfmast, flying }

public class flag{ // Hidden instance data private pole position; private boolean flying; private final String image; // Constructor public flag (String i) { position = pole.lowered; flying = false; image = i; } // Public interface methods public boolean isFlying() { return (flying); } public void raise () { position = pole.flying; flying = true; } public void tribute () { position = pole.halfmast; flying = true;} public void lower () { position = pole.lowered; flying = false; }

} // end class flagSwitching on Enumerationsenum suit { heart, club, diamond, spade }

public static String toString(suit s) { switch (s) { case heart: return ("Love Card"); break; case club: return ("Country Club"); break; case diamond: return ("Best Friend"); break; case spade: return ("Shovel"); break; }} // end toString()Properties of EnumerationsData that has a finite number of elements, not infinite Usually quite small and easily listed, all members are known at the time the type is definedMembers are orthogonal no overlape.g., day of week can't be both Tuesday and ThursdayNatural names for the members exist (these must be represented as identifiers in Java)Ordering is not required, do not need to be sortable, though some (e.g., months) can be ordered

Enumerations as a Class (Text 6.6)enum CFL { Argonauts, TigerCats, Renegades, Alouettes, Eskimos, Stampeders, Lions, RoughRiders }

The compiler (javac) creates a class for usThe class has 8 static objects (instances) of type CFL named Argonauts, TigerCats, etc.Each instance has methods, always, "for free!"equals(), compareTo(), ordinal(), toString()Argonauts comes before TigerCats in a sort, and is ordinal number 0. TigerCats is ordinal number 1, and comes second in a sort, and so on.The static class method valueOf() returns an object of the class based on a string name (can turn user input into an enumeration value this way)Exampleenum CFL { Argonauts, TigerCats, Renegades, Alouettes, Eskimos, Stampeders, Lions, RoughRiders }

CFL team1 = CFL.TigerCats;CFL team2 = CFL.Lions;

if (team1.equals(CFL.Alouettes)) System.out.println(team1 + " is in Montreal");System.out.printf("Team number %d", team1.ordinal());CFL team3 = CFL.valueOf("Renegades");Static ObjectsNormally, we are used to static methods: All members of the class share this method it can't use instance datastatic data: All members of the class share this single variable good for common dataWith enumerations we have static objectsThe instances of the class are staticIf the enumeration has 4 members, there are 4 instances and only 4 instances, which we ACCESS USING THE CLASS NAMEExtending the Flag 2public class flag{ // Use externally as flag.pole.lowered etc. if public private static enum pole { lowered, halfmast, flying }

// Hidden instance data private pole position; private final String image; // Constructor public flag (String i) { position = pole.lowered; image = i; } // Public interface methods public boolean isFlying() { return (!position.equals(pole.lowered)); } public void raise () { position = pole.flying; } public void tribute () { position = pole.halfmast; } public void lower () { position = pole.lowered; }} // end class flagExtending Enumerationsenum CFL2 { // Instanciate the enum, call the constructor // Creates static instances Argonauts("Toronto"), TigerCats("Hamilton"), ...

// Private hidden instance data private final String city;

// Constructor private CFL2(String c) { city = c; }

// Public interface methods public String location() { return (city); }}ExerciseA square in a checker board has several properties:It can be black or it can be greyIt can be occupied or it can be emptyThe piece that occupies it can be red or blackCreate an ADT for a checker board square

Solution 1enum color { black, red, grey }

public class square { private color c; private boolean occupied; private color piece; public square (color initColor) { c = initColor; occupied = false; } public void placePiece(color p) { occupied = true; piece = p; } public void removePiece() { occupied = false; }} // end class squareSolution 2public class square { private boolean black; // true for black, false for grey private boolean occupied; private boolean blackPiece; // true for black, false for red public square (boolean isBlack) { black = isBlack; occupied = false; } public void placePiece(boolean isBlackPiece) { occupied = true; blackPiece = isBlackPiece; } public void removePiece() { occupied = false; }} // end class squareADTs: Interface MethodsConstructor (s) for instances of the classMutators to modify the instance dataAccessors to read/retrieve instance dataCopy Methods to make a new copytoString() so it can be easily printedequals() so deep equality can be checkedcompareTo() so that instances can be ordered and sortedChoicesThe more we learn, the more ways we have to do things and the more choices we have to makeProgramming is an art making the right choices requires experience, insight, and intuitionFactors we consider:efficiency, maintenance, comprehension/simplicity, best practice, experience, requirements, design plan, extendabilitySometimes we get it wrong! Use prototypes to test, refactoring to modify, rewrite/replaceWhile there is no single right way, there are better ways and worse ways of doing thingsHierarchies and ExtensionExtension is a powerful ideaOften, things can be organised into hierarchies, with each lower (sub) category being an extension of the higher (super) category

VehiclePlaneCarBoatSpeedboatPropellerJetTruckPassengerSailboatExtensionExtension is based on properties, with children (the sub-categories) having more properties than the parents (the super-categories)Additional properties means that there are more restrictions and fewer members! Category: Vehicles - All things that move peopleSubcategory: Planes - Vehicles that flyWe can see that there are less planes than vehicles (some vehicles like boats won't fly)Planes was formed by adding a property (can fly) to vehicles, extending vehicles and restricting the category to a subsetSubtypesWe can extend types (e.g., classes) by adding stuff to them to create subtypesThe subtype/subclass has everything the supertype/superclass (its parent) has, but it has extra methods and data

Two important conceptsImplementation Inheritance: A subclass inherits and can use all the methods and data fields of its parentInclusion Polymorphism: An instance of a subclass can be used anywhere an instance of the parent (superclass) can be used

Class A isthe superclass of class Bthe parent of class Ban ancestor of class BClass B is a subclass of class A a child of class Aa descendant of Class A

We extend class A (by adding to it) to create a smaller set of objects (a subset)

RelationshipsIs A, Has AIf we can say a bird is a mammal, then we know we have a subtype relationshipbird will extend mammalIf we can say, a bird has a body temperature, then we know we have a containment relationshipbird will have an instance variable to store body temperatureclasses can contain instances of other classes

public class bird extends mammal { private double temperature; ... etc ...}

Summary (so far)A class is a typeAn object is an instance of a classA subclass is a class that extends its superclassWe call the subclass the child classWe call the superclass the parent classA child inherits from its parentA child extends its parentSince a class is a type, we can say an extended class is a subtype of the parent type/classSubclass Examplepublic class account {

// HIDDEN Instance Data private int balance; private String id; // Constructors public account (String accountID) { id = accountID; balance = 0; }

// Accessors public int getBalance() { return (balance); }

// Mutators public void deposit (int amount) { balance += amount; }} // end class account public class savings extends account {

// Hidden instance data private float interestRate;

// Constructors public savings(String accountID, float rate) { super(accountID); interestRate = rate; }

// Mutators public void calcInterest() { float interest = ((float) balance) * rate; balance += (int) interest; }} // end class savings

The subclassA subclass has access to all methods and data of its parent/super classTo access the parent's constructor, you call the method super() A subclass is created by adding extends parentclass to its definitionParents cannot access anything in subclassesYou can extend a class more than once, and in different ways, to build hierarchiesHierarchiesAnimalsMammalsFishCatsAnimalsMammalsFishCatspublic class Animals { ... }public class Mammals extends Animals { ... }public class Cats extends Mammals { ... }public class Fish extends Animals { ... }

UMLDesigning large programs can become very complicatedHundreds of classes and relationships (is a, has a)We have formal modelling languages to design large systemsIn OOP, the most popular and common language is UML Unified Modelling LanguageUML NotationUML is a framework it is not a rigid set of rules, it is intended to be adapted to fit your needThere is a standard notation however for formal purposesUML is currently in version 2.2There are 14 different diagram typesWe will look at Class DiagramsSee: http://en.wikipedia.org/wiki/Class_diagramBasic Class NotationClass nameDataMethods

VisibilityClass members (data and methods) are preceded with symbols to indicate visibility"+" Public "-" Private "#" Protected (See Appendix 3, pg 920 if you are interested)"_" Static"/" Derived (can be combined with one of the others)Derived data is not storedit is calculated e.g., age = date birthdate), or obtained in some other way (e.g., from an external sensor)RelationshipsSubtypes point to their parents with a hollow arrow (inheritance)Components point to their containing (holder) with a diamond arrow Hollow: Aggregation, part can exist aloneSolid: Containment, part cannot exist without holderOther notations exist for other relationships

UML ExampleAlso see Figures 8.2, 8.3

Notation Summary

UML is complicated and very detailedVisual alternative to codeCan be very useful for organising and communicating thoughts and ideasThis is NOT a course on UMLSingle InheritanceConsider a seaplane it can be both a boat and a planeIt would be nice to have it as a subclass of both Boats and Planes (multiple inheritance = multiple parents)Java DOES NOT permit thisA class can have ONE direct parentSingle inheritance = one parent onlySeaplane must be a Boat OR a Plane

VehicleBoatsPlanesSeaplaneOverloadingWhen two methods have the same name but different type signatures we say that the method is overloadedWe have seen this before with methods like sortint[] voiddouble[] voidWe can do this for methods we write as well, such as when we want multiple constructors At least one of the parameters must be different if we overload a method

Overloading = same name but different parametersOverridingOverriding is NOT overloading but it is very similarWe can have two methods with the same name and the SAME PARAMETERS if they are in subclassesIn overloading, the parameters determine which method to useIn overriding, the class determines which method to useExample: Overridingpublic class point { private int x, y; public point (int a, int b) { x = a; y = b; } public int getX () { return (x); } public int getY () { return (y); } public boolean onXAxis () { return (x == 0); } public boolean onYAxis () { return (y == 0); } public void display () { System.out.printf("(%d, %d)", x, y); }} ... In a DIFFERENT FILE ...public class point3D extends point { private int z; public point3D (int a, int b, int c) { super (a, b); z = c; } public int getZ () { return (z); } public boolean onZAxis () { return (z == 0); } public void display () { // OH NOES x, y are PRIVATE, must use accessors! System.out.printf("(%d, %d, %d)", getX(), getY(), z); }}Example: Overriding (con't)point p1 = new point (10, 20);point3D p2 = new point3D (30, 40, 50);

boolean x1 = p1.onXAxis();p1.display();

// Calls onXAxis() for point, not point3D// onXAxis() is INHERITED from the parentboolean x2 = p2.onXAxis();

// Calls display for point3d// OVERRIDES display() that was inherited from parentp2.display();

Exercise (Quick'n Easy)Write a method call int2bool to convert an integer to a boolean. Turn 0 into false, 1 into true, and raise an exception for any other value.Solutionpublic static boolean int2bool (int n) throws Exception { switch (n) { case 0: return (false); case 1: return (true); default: throw new Exception ("Invalid value."); }}

Idea: Instead of checking for "bad data", process good data and then consider everything else as invalid. Now we know about sub-types ...

To DoRead Chapter 8 on Advanced OOP, we're not quite done it, so some parts will not be familiar, yetRead Chapter 9 on exceptions it should make more sense now you understand that classes can be extendedWe are almost done EVERYTHING up to 10.3Do Assignment 6 in the lab today