Presentation is loading. Please wait.

Presentation is loading. Please wait.

Object-Oriented Programming: Classes, Inheritance, and Interfaces

Similar presentations


Presentation on theme: "Object-Oriented Programming: Classes, Inheritance, and Interfaces"— Presentation transcript:

1 Object-Oriented Programming: Classes, Inheritance, and Interfaces
Wellesley College CS230 Lecture 06 Thursday, February 15 Handout #14 Reading: Downey: Chapter 13; Carrano: p Problem Set: Assignment #2 due Friday, Feburary 23

2 Object-Oriented Programming (OOP)
In OOP, computations are described in terms of collections of stateful objects that communicate by passing messages to one other. Objects are like actors in a play; the programmer is the playwright & director. A class specifies the behavior (variables and methods) of a collection of objects = the instances of the class. Related classes can be organized into inheritance hierarchies, which allow one class to extend and/or override the variables and methods of other classes. OOP is one of several programming paradigms. Others include imperative programming, function-oriented programming, logic programming. CS251 Programming Languages covers these. IMHO, OOP is overhyped – function-oriented programming with state (as embodied in Scheme & OCAML) does everything OOP can do plus much, much more! Take CS251 to See The Light.

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 new instance. Via this, it can refer to all (including private) instance variables of the new instance that are declared in the method’s class. An instance method specifies how an instance (the receiver = this) responds to a message. It can also refer to all of the receiver’s instance variables that are declared in the method’s class. Note that the receiver is really just an argument with a special name (this). A class method is a receiverless message that corresponds to functions/procedures in other languages. It cannot refer to this, since there is no receiver.

4 Class Example: A Counter Class
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(); 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();}

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.

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 by other classes in the same package, particularly subclasses of the given class. E.g., we’ll soon see subclasses of Counter that need to access/change the count instance variable. Public should only be used for instance/class variables as public when (1) their implementation will never change and (2) it’s OK for the whole world to see/change their value. (Can prevent changing public variables like Color.red by declaring them final.)

7 Inheritance: A Resettable Counter
public Object(); public boolean equals (Object x); // this = x public String toString(); // string rep. of pointer Object subclasses public Counter (); public void inc (); // increments count public String toString(); // Overrides Object’s definition Counter superclasses Resettable Counter public ResettableCounter(); public void reset (); // resets count to 0

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(); }

9 Inheritance: An Inittable Counter
public Object(); public boolean equals (Object x); // this = x public String toString(); // string rep. of pointer Object subclasses public Counter (); public void inc (); // increments count public String toString(); // overrides Object’s definition Counter superclasses Resettable Counter public ResettableCounter(); public void reset (); // resets count to 0 Inittable Counter public InittableCounter(); public InittableCounter(int init); // initializes count to init

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]; }

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;

12 The instanceof Operator
Counter c = new Counter(); c instanceof Object → true c instanceof Counter → true c instanceof ResettableCounter → false c instanceof InittableCounter → false c instanceof Point → false Object subclasses Counter superclasses Resettable Counter InittableCounter i = new InittableCounter(); i instanceof Object → true i instanceof Counter → true i instanceof ResettableCounter → true i instanceof InittableCounter → true i instanceof Point → false Inittable Counter

13 Inheritance: An Equatable Counter
public Object(); public boolean equals (Object x); // this = x public String toString(); // string rep. of pointer Object subclasses public Counter (); public void inc (); // increments count public String toString(); // overrides Object’s definition Counter superclasses Resettable Counter public ResettableCounter(); public void reset (); // resets count to 0 Inittable Counter public InittableCounter(); public InittableCounter(int init); // initializes count to init Equatable Counter public EquatableCounter(); public boolean equals (Object x); // this.count = x.count

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; } Counter c = new Counter(); Counter c2 = new Counter(); Counter c3 = c; Counter r = new ResettableCounter(); Counter e = new EquatableCounter(); c.equals(c2) → false c.equals(c3) → true c.equals(r) → false c.equals(e) → false e.equals(c) → true // asymmetric! e.equals(c2) → true e.equals(c3) → true e.equals(r) → true c.inc(); e.inc(); e.equals(c) → true e.equals(c2) → false e.equals(r) → false

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() + ")"; } }

16 Manipulating Immutable Points
public static int sumCoordsVars (IPointVars p) { return p.getX() + p.getY(); } public static int sumCoordsArray (IPointArray p) { 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.

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)) → 3 sumCoords(new IPointArray(3,4)) → 7 An interface specifies the types of some instance method contracts. Gives new information to Java type checker

18 An IPoint Abstract Class
A class must be declared abstract if any of its methods are declared abstract. 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)) → 3 sumCoords(new IPointArray(3,4)) → 7 A method without a body is declared abstract. An abstract class may have concrete methods; these can use abstract methods. Use extends rather than implements with abstract class

19 Enumerations: A Very Handy Interface

20 Motivating Enumerations: Manipulating File Lines

21 A File Line Enumeration

22 Using the File Line Enumeration

23 Comparable: Another Handy Interface


Download ppt "Object-Oriented Programming: Classes, Inheritance, and Interfaces"

Similar presentations


Ads by Google