390 likes | 2.16k Views
Explore the fundamentals of Object-Oriented Programming (OOP) in Java, including objects, classes, inheritance, and polymorphism. Learn how to structure programs using objects and understand the benefits of hiding state and using interfaces.
E N D
Object Oriented Programming • OOP: Many things to many people • Some common elements • Objects = state + behavior • Interfaces • Classes • Subtyping, polymorphism • Inheritance and overriding • We’ll look at these in the context of Java
The Java Programming LanguageTM • C-like syntax • Safe execution model • Static type checking • No uninitialized variables • A few dynamic checks • Array bounds checking • No pointer arithmetic • No dangerous type casts • “Mostly Object Oriented”
Objects • A chunk of state (i.e. variables, a.k.a. fields) with some behavior (i.e. operations, a.k.a. methods) int x, y;void set_pos(int newx, int newy) { x = newx; y = newy; }void move_up() { set_pos(x, y + 20); } • Structure a program as a collection of objects • E.g. data structures, files, GUI widgets, devices • …, numbers, algorithms, … everything!
Features of Java Objects • State (often hidden) • Methods operating on and revealing state • Dynamic dispatch • Method implementation selected at runtime • Reference semantics • Different variables may refer to the same object • Types describing how objects may be used
Hiding State • Improve modularity by hiding information [Parnas] int x, y;void set_pos(int newx, int newy){ x = newx; y = newy; }void move_up(){ set_pos(x, y + 20); } • x and y are not accessible outside the object • We can change the object’s implementation without affecting users of the object • E.g. int x, y --> int coords[2]
Hiding State in Java • Keywords: public, private private int x, y;public void set_pos(int newx, int newy){ x = newx; y = newy; }public void move_up(){ set_pos(x, y + 20); } • Public variables and/or private methods are also allowed
Interfaces • The parts of an object accessible from outside public void set_pos(int newx, int newy);public void move_up(); • Objects come with a formal or informal specification that defines what the interface does
Method Invocation • We need to specify which object is used when we call a method p1.set_pos(100, 0);p1.move_up();p2.set_pos(100, 20); • We look up p1 and p2 at runtime to see which implementations of set_pos and move_up to use • “Dynamic dispatch”/“late binding”/“virtual call” • The same line of code can get different implementations for different values of p1
Object References • p1 and p2 are object references • “p1 = p2” has reference semantics • p1 and p2 end up referring to the same object • An object reference always refers to a valid object (references cannot be forged) • Except “null” references are allowed (unfortunately) • Every object reference either refers to a valid object or is null (like ‘option’ in ML)
Object Equality • Reference equality tests if two references are the same object • “p1 == p2” • “Deep” equality tests if two objects represent the same thing • “p1.equals(p2)” • E.g. p1 and p2 both represent (100, 20), p1.equals(p2) but p1 != p2
Classes • Need families of objects with the same methods but with different internal state • Java solution: group objects into classes class Point { private int x, y; public void set_pos(int newx, int newy) {…} public void move_up() {…} }
Features of Java Classes • All objects of a given class have the same methods • Create new objects of a given class (“new Point()”) • Use inheritance to share code between classes • Classes define boundaries for hiding information • Per-class code and data (“static”) • A class defines a type and a tag for objects
Creating Objects • Create an object with “new classname” • Automatically calls a constructor method • Helpful for establishing object invariants class Point { private int x, y;public Point(int initx, int inity) { x = initx; y = inity; } …}Point p = new Point(100, 100);
Inheritance • Can declare one class to be a subclass of another • Each method (and field) in the superclass can be inherited by the subclass class ColoredPoint extends Point { public void set_color(Color color) {…}} • ColoredPoint gets methods set_pos and move_up from Point • This is just a way to reuse code
Overriding • Superclass methods can be overridden class ColoredPoint extends Point { public void set_pos(int newx, int newy) { x = newx; y = newy; set_color(BLACK); } public void set_color(Color color) {…}} • ColoredPoint only gets method move_up from Point • This allows specialization of reused code
Fun With Inheritance/Overriding • This invokes Point.move_up on p • By default, methods operate on “this” (current obj.) • Which set_pos is called? • ColoredPoint.set_pos !!! • Because even though we’re in the code for a Point, methods are always selected according to the dynamic (run-time) class of the object ColoredPoint p = new ColoredPoint();p.move_up();
Fun With Inheritance/Overriding class Point { private int x, y; public void set_pos(int newx, int newy) { x = newx; y = newy; } public void move_up() { set_pos(x, y + 20); } }class ColoredPoint extends Point { public void set_pos(int newx, int newy) { x = newx; y = newy; set_color(BLACK); } public void set_color(Color color) {…}}
Class Hierarchy • The graph of subclass relationships Object String Number Integer Float • Every class has a superclass, except for the root class “Object”
Controlling Subclassing/Overriding • A Java class can be declared “final” • No subclass can be created final class ColoredPoint extends Point { … } • A Java method can be declared “final” • It cannot be overriden in a subclass class ColoredPoint extends Point { final public void set_color(Color color) {…} } • Can improve efficiency, and guide reuse
Multiple Inheritance • Can cause problems with ambiguities • What if Colorable defines a set_pos method? • Java allows at most one superclass • (This code is not legal) class Colorable { public void set_color(Color color) {…}}class ColoredPoint extends Point, Colorable{}
Access Control • We’ve seen “public” and “private” • “private”: field or method only accessible by code in the same class • “protected” • Field or method only accessible by code in the same class or a subclass • In Java, classes can be grouped into packages, which also affect access control
Static Methods and Fields • Every method or field belongs to some class • Sometimes we want methods or fields that belong to no particular object (global variables, functions) • “static” methods and fields class Math { static double PI = 3.14159; static double pow(double x, double n) {…} …}
Base Types in Java • Not everything is an object (unlike, e.g. Smalltalk) • Primitive numeric types: byte, short, int, long, char, float, double • Primitive boolean type • Makes implementation easier, and more like C/C++, but the language is less uniform • Standard “wrapper classes” exist to package primitive values inside objects • e.g. “new Integer(42);”
Types • What is the type of an object reference? p.set_pos(100, 100); • To check whether this is valid, the type of p must specify which methods are available • We could have types like this:[public void set_pos(int newx, int newy),public void move_up()] • But these get large and nasty
Class Types • Let the type of an object reference be the name of a class Point p;p.set_pos(100, 100); • Check call by examining the methods in class Point • Makes it easy to write type declarations static void move_up_twice(Point p) { p.move_up(); p.move_up(); }
Structural Subtyping class ColoredPoint { public void set_pos(int newx, int newy) {…} public void move_up() {…} public void set_color(Color color) {…}} • Can we pass a ColoredPoint to move_up_twice? • Each method of Point is supported by ColoredPoint • Therefore, as far as one can tell by looking at interfaces, “every ColoredPoint is also a Point” • We could say ColoredPoint is a subtype of Point • A form of polymorphism: move_up_twice can be applied to different kinds of objects
Behavioral Subtyping class Graphic { public void draw() {…}}class Cowboy { public void draw() {…} public void shoot() {…}} • Make Cowboy a subtype of Graphic only if Cowboy satisfies the specification of Graphic [Wing] • But we can’t check this automatically
Subtyping in Java • Subtype relationships declared explicitly by subclassing class ColoredPoint extends Point { public void set_pos(int newx, int newy) {…} public void move_up() {…} public void set_color(Color color) {…}} • Simple, but not very flexible • Sometimes we want subtype relationships that the original programmer didn’t think of
Inheritance vs Subtyping • In Java, subclassing controls both subtyping and inheritance • These really should be separated • Sometimes we want to reuse code without creating a subtype relationship • Sometimes we want a subtype relationship without reusing code
Arrays in Java • All arrays created dynamically • Size specified at runtime • Bounds checking at runtime • Arrays are special subclasses of Object • In particular, arrays are accessed by reference int[] numbers = new int[100]; for (int i = 0; i < numbers.length; i++) { numbers[i] = i; } System.out.println(numbers[50]);
Arrays and Subtyping • In Java: A subtype of B A[] is a subtype of B[] • This allows some useful code to be written static void printAll(Object[] things) { for (int i = 0; i < things.length; i++) { System.out.println(things[i].toString()); } }ColoredPoint[] coloredPoints = …;printAll(coloredPoints);
Java Arrays are Broken static void evilPrintAll(Object[] things) { … things[0] = new Point(); // typechecks!}ColoredPoint[] coloredPoints = …;evilPrintAll(coloredPoints);coloredPoints[0].set_color(BLACK); // BOOM • To prevent this, every store into an array of objects incurs a runtime check --- YUCK • A[] should never be a subtype of B[] (unless A=B)
Java Interface Classes • Java “interface”: a special kind of class • Contains no fields or method implementations • Contains only a list of methods that must be implemented by subclasses interface Colorable { public void set_color(Color color);}class ColoredPoint extends Pointimplements Colorable { public void set_color(Color color) {…}}
Interface Classes • Java allows multiple inheritance of interfaces • No ambiguity about which method body to inherit • Since each interface declares a type, we can now have types that are subtypes of more than one type interface Colorable { public void set_color(Color color);}interface Positionable { public void set_pos(int newx, int newy);}class ColoredPoint extends Pointimplements Colorable, Positionable {…}
Limitations of Java’s Type System • Consider a general stack class class Stack { … public void push(Object obj) {…} public Object pop() {…} }Stack s = new Stack(); s.push(new Point());Point p = s.pop(); // Doesn’t typecheck • There’s no way to parameterize Stack with the type of objects that it will contain
Downcasting • Solution: add a “downcast” declaring that the popped Object is really a Point • Runtime checks ensure that it is really a Point Stack s = new Stack(); s.push(new Point());Point p = (Point)s.pop(); • Slow, can lead to unfortunate runtime errors • Even the best languages seem to need it sometimes • Also have instanceof: “if (p instanceof Point) …”
Tagging (“Runtime Types”) • “instanceof” and downcasting require every object to retain a class tag at runtime • Each class has a unique tag • Tag sometimes referred to as “dynamic type” of the object • Tags accessible to the programmer via “obj.getClass()” (reflection)
Frameworks • Library design: Reuse code by inheriting and specializing framework base classes • Often used for GUIs (e.g. AWT, Swing, MFC) • “Given generic app, specialize it to what you want” AppWin AppButton Application Window Button Graphics UI Lib Container Containee Container Lib
Frameworks • Advantages over other approaches (e.g. “layered libraries”) • Get started quickly (prototyping) • Can hide control flow in the framework • May allow more flexible customization • Disadvantages • Dynamic dispatch can lead to spaghetti code • Interface between (e.g.) AppWin and Window code is complex, hard to specify, and fragile