Object-oriented Programming in Java
What is OOP? The goal is (subtype) polymorphism Achieved by Classes (user-defined types) Inheritance (is-a, substitutability) Dynamic Function Binding Function to run is bound according to the dynamic type of the object
Inheritance extends keyword Terminology: super superclass, parent class, base class subclass, child class, derived class super C++ - declare as virtual to get dynamic binding, static is default Java – dynamic binding is default, declare as final to get static binding
Upcasting Storing a reference to a subtype in a supertype variable Makes sense because of the is-a relationship Allows any subtype object to be used in a context expecting a supertype object Employee e = new SalariedEmployee();
The instanceof operator Returns true if the left operand is the same type or a subtype of the right operand new HourlyEmployee() instanceof Employee is true Often used before downcasting To avoid an exception
Polymorphism Dynamic variation of behavior According to an object’s dynamic type Calls the function corresponding to the type the reference indicates at the moment Invisibly to the program Employee e = new HourlyEmployee(); e.computePay(); e = new SalariedEmployee(); e.computePay(); // A different function! Example: Figure 2 (Allison, Nov. 1999)
Benefits of OOP High degree of separation among components Low coupling Insulates components from changes in other components Example: payroll program Uses the Employee interface The dynamic types are invisible
Downcasting When an object must be interpreted as a subtype When extracting from a collection, for example Must use with care The object may not be the type you’re expecting Checked at runtime Examples: Figures 4, 5 (Allison, Nov. 1999)
Abstract Classes Not meant to be instantiated Define an interface Also define part of the implementation Subclasses complete the implementation abstract keyword Both for classes and methods
java.lang.Object The Mother of all Classes Object methods: All objects are subtypes of Object Object methods: int hashCode( ); boolean equals(Object); String toString( ); Among others…
Object.toString Provides a String representation of an object Prints the class name and the hashCode Should override
Object.equals(Object) Used for a value-based equality test Override carefully: Test == this first if true, return true Test instanceof TheClass if false, return false Then check all the fields Use equals() recursively for object fields Can super.equals() for inherited fields Examples: ColorPoint (next slide) and SuperEquals.java Always override hashCode() if you override equals()
ColorPoint public boolean equals(Object other) { if (this == other) return true; else if (!(other instanceof ColorPoint)) return false; ColorPoint p = (ColorPoint) other; return (super.equals(p) && p.color.equals(this.color)); } Instance variables in parent class, Point: Instance variable in child class, ColorPoint: int x, y Color color
Floating-point Fields Don’t compare for equality with ==! Has to do with special values (NaN, etc.) Convert floats to int with Float.floatToIntBits Convert doubles to long with Double.doubleToLongBits Compare the resulting integers with ==
hashCode Used to associate an object with an int Used in hash tables and other containers Should be “as unique as possible” Rules: Boolean: (f ? 0 : 1) byte, char, or short: (int) f Long: (int)(f ^ (f>>>32)) Float: Float.floatToIntBits(f) Double: Double.doubleToLongBits(f) Combine with prime numbers: h = 37*f1; h = 37*h;… Objects: combine their hashcodes (see pp. 197-198)