Object-Oriented Programming: Classes, Inheritance,...
Transcript of Object-Oriented Programming: Classes, Inheritance,...
1
06- 1
Object-Oriented Programming:Classes, Inheritance, and Interfaces
Reading: Downey: Chapter 13; Carrano: p. 126-134Problem Set: Assignment #2 due Friday, Feburary 23
Wellesley College CS230Lecture 06
Thursday, February 15Handout #14
06- 2
Object-Oriented Programming (OOP)
• In OOP, computations are described in terms of collectionsof stateful objects that communicate by passing messagesto one other.
• Objects are like actors in a play; the programmer is theplaywright & director.
• A class specifies the behavior (variables and methods) of acollection of objects = the instances of the class.
• Related classes can be organized into inheritancehierarchies, which allow one class to extend and/or overridethe variables and methods of other classes.
• OOP is one of several programming paradigms. Othersinclude imperative programming, function-orientedprogramming, logic programming. CS251 ProgrammingLanguages covers these.
• IMHO, OOP is overhyped – function-oriented programmingwith state (as embodied in Scheme & OCAML) doeseverything OOP can do plus much, much more! Take CS251to See The Light.
2
06- 3
The Anatomy of a Java Class
A Java class can contain 5 kinds of declarations:• 2 kinds of variable declarations:
– an instance variable for every instance of the class– a class (static) variable in exactly one place (the class
itself)• 3 kinds of method declarations.
– A constructor method specifies how to create a newinstance. Via this, it can refer to all (including private)instance variables of the new instance that are declaredin the method’s class.
– An instance method specifies how an instance (thereceiver = this) responds to a message. It can also referto all of the receiver’s instance variables that aredeclared in the method’s class. Note that the receiver isreally just an argument with a special name (this).
– A class method is a receiverless message thatcorresponds to functions/procedures in other languages.It cannot refer to this, since there is no receiver.
06- 4
Class Example: A Counter Class
import java.util.*; // imports Vector
public class Counter {
// Instance variables: protected int count; private int id;
// Class variable: private static Vector<Counter> all = new Vector<Counter>();
// Constructor method: public Counter () { all.add(this); this.id = all.size() // Here and below, can punt “this.” this.count = 0; displayCounters(); }
// Instance methods: public void inc () { this.count++; displayCounters();}
public String toString () { return "[" + this.id + “ of “ + all.size() + ":" + this.count + "]"; }
// Class methods: public static void displayCounters() { for (int i = 0; i < all.size(); i++) { System.out.print(all.get(i) + “; “); } System.out.println(); }
public static void main (String [] args) { Counter a = new Counter(); a.inc(); Counter b = new Counter(); a.inc(); b.inc(); a.inc(); }
}
3
06- 5
Information Flow: Public/Protected/Private
Within a class C, any phrase (statement/expression) P can access:• public class variables of any class;• protected class variables of classes in the same package as C;• private class variables of C;• public instance variables of any object mentioned in P;• protected instance variables of any object O mentioned in P,
where O’s class is in the same class as C.• private instance variables of any instance of C.Additionally:• Any method body can access all parameter variables.• A constructor method body can access the newly constructed
instance via this.• An instance method body can access the receiver object via this.
06- 6
When to use private and protected?
Private should be the default:• This helps to preserve invariants: e.g., counter id is never changed
(immutable); counters in the all vector are sorted by id.• Gives flexibility to implementer to change representations under the
hood.
Protected is used for instance/class variables that need to be accessed byother classes in the same package, particularly subclasses of the givenclass. E.g., we’ll soon see subclasses of Counter that need toaccess/change the count instance variable.
Public should only be used for instance/class variables as public when (1) theirimplementation will never change and (2) it’s OK for the whole world tosee/change their value. (Can prevent changing public variables likeColor.red by declaring them final.)
4
06- 7
Inheritance: A Resettable Counter
Object
Counter
ResettableCounter
public Object();public boolean equals (Object x); // this = xpublic String toString(); // string rep. of pointer
public Counter ();public void inc (); // increments countpublic String toString(); // Overrides Object’s definition
public ResettableCounter();public void reset (); // resets count to 0
supe
rcla
sses
subclasses
06- 8
Inheritance: Resettable Counter Code
public class ResettableCounter extends Counter {
public void reset() { count = 0; // Won’t work if count is declared private in Counter! displayCounters(); } public static void main (String [] args) { ResettableCounter a = new ResettableCounter(); // [1 of 1:0]; a.inc(); // [1 of 1:1]; Counter b = new Counter(); // [1 of 2:1]; [2 of 2:0]; a.inc(); // [1 of 2:2]; [2 of 2:0]; b.inc(); // [1 of 2:2]; [2 of 2:1]; a.reset(); // [1 of 2:0]; [2 of 2:1]; a.inc(); // [1 of 2:1]; [2 of 2:1]; }}
// The following is implicitly declared:public ResettableCounter() { super(); }
5
06- 9
Inheritance: An Inittable Counter
Object
Counter
ResettableCounter
public Object();public boolean equals (Object x); // this = xpublic String toString(); // string rep. of pointer
public Counter ();public void inc (); // increments countpublic String toString(); // overrides Object’s definition
public ResettableCounter();public void reset (); // resets count to 0
supe
rcla
sses
subclasses
InittableCounter
public InittableCounter();public InittableCounter(int init); // initializes count to init
06- 10
Inheritance: Inittable Counter Code
public class InittableCounter extends ResettableCounter { public InittableCounter (int init) { super(); // Call nullary Counter constructor; count = init; displayCounters(); } public InittableCounter () { this(0); } public static void main (String [] args) { InittableCounter a = new InittableCounter(17); // [1 of 1:0]; // [1 of 1:17]; a.inc(); // [1 of 1:18]; InittableCounter b = new InittableCounter(); // [1 of 2:18]; [2 of 2:0]; // [1 of 2:18]; [2 of 2:0]; a.inc(); // [1 of 2:19]; [2 of 2:0]; b.inc(); // [1 of 2:19]; [2 of 2:1]; a.reset(); // [1 of 2:0]; [2 of 2:1]; a.inc(); // [1 of 2:1]; [2 of 2:1]; }}
6
06- 11
Common Constructor Method Gotchas
public InittableCounter (int count) { count = count; // X // use this.count = count;}
public InittableCounter (int init) { int count = init; // X // use count = init;}
06- 12
The instanceof Operator
Counter c = new Counter();c instanceof Object → truec instanceof Counter → truec instanceof ResettableCounter → falsec instanceof InittableCounter → falsec instanceof Point → false
Object
Counter
ResettableCounter
supe
rcla
sses
subclasses
InittableCounter
InittableCounter i = new InittableCounter();i instanceof Object → truei instanceof Counter → truei instanceof ResettableCounter → truei instanceof InittableCounter → truei instanceof Point → false
7
06- 13
Inheritance: An Equatable Counter
Object
Counter
ResettableCounter
public Object();public boolean equals (Object x); // this = xpublic String toString(); // string rep. of pointer
public Counter ();public void inc (); // increments countpublic String toString(); // overrides Object’s definition
public ResettableCounter();public void reset (); // resets count to 0
supe
rcla
sses
subclasses
InittableCounter
public InittableCounter();public InittableCounter(int init); // initializes count to init
EquatableCounter
public EquatableCounter();public boolean equals (Object x); // this.count = x.count
06- 14
Inheritance: EquatableCounter Code
public class EquatableCounter extends InittableCounter { public boolean equals (Object x) { if (! (x instanceof Counter)) { return false; } else { Counter c = (Counter) x; // Downcast will succeed return this.count == c.count; }}
e.equals(c) → true // asymmetric!e.equals(c2) → truee.equals(c3) → truee.equals(r) → truec.inc(); e.inc();e.equals(c) → truee.equals(c2) → falsee.equals(c3) → truee.equals(r) → false
Counter c = new Counter();Counter c2 = new Counter();Counter c3 = c;Counter r = new ResettableCounter();Counter e = new EquatableCounter();c.equals(c2) → falsec.equals(c3) → truec.equals(r) → falsec.equals(e) → false
8
06- 15
Two Implementations of Immutable Points
public class IPointVars { private int x, y; // Represent coords with two int variables. public IPointVars (int x, int y) {this.x = x; this.y = y;} public int getX() { return x; } public int getY() { return y; } public String toString() { return "(" + getX() + "," + getY() + ")"; }}
public class IPointArray {
private int[] ints = new int[2]; // Represent coords with two-slot array.
public IPointArray (int x, int y) {ints[0] = x; ints[1] = y;} public int getX() { return ints[0]; } public int getY() { return ints[1]; } public String toString() { return "(" + getX() + "," + getY() + ")"; }}
06- 16
Manipulating Immutable Points
public static int sumCoordsVars (IPointVars p) { return p.getX() + p.getY(); }
public static int sumCoordsArray (IPointArray p) { return p.getX() + p.getY(); }
The sumCoord methods are the same modulo the point type. Can we define a single sumCoords() method that works on
instances of both classes? Yes! By using (1) an interface or (2) an abstract class.
9
06- 17
An IPoint Interface
public interface IPoint { public int getX(); public int getY(); public String toString();}
public class IPointVars implements IPoint { … same impl. as before …}public class IPointArray implements IPoint { … same impl. as before …}
public static int sumCoords (IPoint p) { return p.getX() + p.getY(); }
sumCoords(new IPointVars(1,2)) → 3sumCoords(new IPointArray(3,4)) → 7
Gives new informationto Java type checker
An interface specifies the types ofsome instance method contracts.
06- 18
An IPoint Abstract Class
public abstract class IPoint { public abstract int getX(); public abstract int getY(); public String toString() { return "(" + getX() + "," + getY() + ")"; }}
public class IPointVars extends IPoint { … same impl. as before except no toString() method …}public class IPointArray extends IPoint { … same impl. as before except no toString () method …}
public static int sumCoords (IPoint p) { return p.getX() + p.getY(); }
sumCoords(new IPointVars(1,2)) → 3sumCoords(new IPointArray(3,4)) → 7
Use extends rather thanimplements with abstract class
A class must be declared abstract if anyof its methods are declared abstract.
A method without a bodyis declared abstract.
An abstract class may have concretemethods; these can use abstract methods.