Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Object-oriented Programming, Slides of Object Oriented Programming

In this simple form of aggregation, constituent objects can be shared between objects, and their lifetimes are independent of the lifetime of the aggregate ...

Typology: Slides

2021/2022

Uploaded on 09/12/2022

journalyyy
journalyyy 🇬🇧

4.7

(12)

216 documents

Partial preview of the text

Download Object-oriented Programming and more Slides Object Oriented Programming in PDF only on Docsity! CS211, Fall, 1999. KAM OOP.fm 1/71 Object-oriented Programming Reference: Chapter 6 of A Programmer’s Guide to Java Certification: A Comprehensive Primer. CS211, Fall, 1999. KAM Object-oriented Programming 2/71 Overview • The inheritance relationship: is-a • The aggregation relationship: has-a • Overridden and overloaded methods • The keyword super • Variable shadowing • Constructors and constructor chaining using this() and super() • Single implementation inheritance, multiple interface inheritance and supertypes • Assigning, casting and passing references • The instanceof operator • Polymorphism and dynamic method lookup • Encapsulation • Choosing between inheritance and aggregation CS211, Fall, 1999. KAM Object-oriented Programming 3/71 Extensibility by Linear Implementation Inheritance • One fundamental mechanism for code reuse. • The new class inherits all the members of the old class - not to be confused with accessibility of superclass members. • A class in Java can only extend one other class, i.e. it can only have one immediate superclass. • The superclass is specified using the extends clause in the header of the subclass. • The definition of the subclass only specifies the additional new and modified mem- bers in its class definition. • All classes extend the java.lang.Object class. CS211, Fall, 1999. KAM Object-oriented Programming 4/71 Example 1 Extending Classes class Light { // (1) // Instance variables private int noOfWatts; // wattage private boolean indicator; // on or off private String location; // placement // Static variable private static int counter; // no. of Light objects created // Constructor Light() { noOfWatts = 50; indicator = true; location = new String("X"); } // Instance methods public void switchOn() { indicator = true; } public void switchOff() { indicator = false; } public boolean isOn() { return indicator; } // Static methods public static void writeCount() { System.out.println("Number of lights: " + counter); } //... } CS211, Fall, 1999. KAM Object-oriented Programming 9/71 Aggregation • A major mechanism for code reuse mechanism is aggregation. • Aggregation defines the relationship has-a (a.k.a. whole–part relationship) between an instance of a class and its constituents (a.k.a. parts). • In Java, an aggregate object cannot contain other objects. • It can only have references to its constituent objects. • The has-a relationship defines an aggregation hierarchy. • In this simple form of aggregation, constituent objects can be shared between objects, and their lifetimes are independent of the lifetime of the aggregate object. CS211, Fall, 1999. KAM Object-oriented Programming 10/71 Illustrating Inheritance Figure 2 Inheritance Relationship between String and Object classes java.lang.Object equals() getClass() notify() ... java.lang.String equals() substring() length() ... CS211, Fall, 1999. KAM Object-oriented Programming 11/71 Example 2 Illustrating Inheritance // String class is a subclass of Object class class Client { public static void main(String args[]) { String stringRef = new String("Java"); // (1) System.out.println("(2): " + stringRef.getClass()); // (2) System.out.println("(3): " + stringRef.length()); // (3) Object objRef = stringRef; // (4) // System.out.println("(5): " + objRef.length()); // (5) Not OK. System.out.println("(6): " + objRef.equals("Java")); // (6) System.out.println("(7): " + objRef.getClass()); // (7) stringRef = (String) objRef; // (8) System.out.println("(9): " + stringRef.equals("C++")); // (9) } } Output from the program: (2): class java.lang.String (3): 4 (6): true (7): class java.lang.String (9): false CS211, Fall, 1999. KAM Object-oriented Programming 12/71 Inheriting from the Superclass • The subclass String inherits the method getClass() from the superclass Object - this is immaterial for a client of class String System.out.println("(2): " + stringRef.getClass()); // (2) Extending the Superclass • The subclass String defines the method length(), which is not in the superclass Object, thereby extending the superclass. System.out.println("(3): " + stringRef.length()); // (3) Upcasting • A subclass reference can be assigned to a superclass reference, because a subclass object can be used where a superclass object can be used. Object objRef = stringRef; // (4) creates aliases • Methods exclusive to the String subclass cannot be invoked via the superclass reference: System.out.println("(5): " + objRef.length()); // (5) Not OK. CS211, Fall, 1999. KAM Object-oriented Programming 13/71 Method Overriding • The equals() method is redefined in the String class with the same signature (i.e. method name and parameters) and the same return type. System.out.println("(6): " + objRef.equals("Java")); // (6) • The compiler can check that the Object class does define a method called equals(). Polymorphism and Dynamic Method Binding • The ability of a superclass reference to denote objects of its own class and its sub- classes at runtime is called polymorphism. • The method invoked is dependent on the actual (type of) object denoted by the ref- erence at runtime. • The actual method is determined by dynamic method lookup. System.out.println("(6): " + objRef.equals("Java")); // (6) System.out.println("(7): " + objRef.getClass()); // (7) • At (6), dynamic method lookup results in the equals() method from the String class being executed, and not the one in the Object class. CS211, Fall, 1999. KAM Object-oriented Programming 14/71 • At (7), dynamic method lookup determines that the method getClass() inherited from the Object class to be executed - leading to a "search" up the inheritance hier- archy. Downcasting • Casting the value of a superclass reference to a subclass type is called downcasting, and requires explicit casting. stringRef = (String) objRef; // (8) System.out.println("(9): " + stringRef.equals("C++")); // (9) • The cast can be invalid at runtime! • A ClassCastException would be thrown at runtime. • Use the instanceof operator to determine the runtime type of an object before any cast is applied. if (objRef instanceof String) { stringRef = (String) objRef; System.out.println("(9): " + stringRef.length); } CS211, Fall, 1999. KAM Object-oriented Programming 19/71 Output from the program: Large bill: 500.0 Large bill: 500.0 Small bill: 50.0 Large bill Small bill Small bill No bill CS211, Fall, 1999. KAM Object-oriented Programming 20/71 Variable Shadowing • A subclass cannot override variable members of the superclass, but it can shadow them. • A subclass method can use the keyword super to access inherited members, including shadowed variables. • When a method is invoked on an object using a reference, it is the class of the cur- rent object denoted by the reference, not the type of the reference, that determines which method implementation will be executed. • When a variable of an object is accessed using a reference, it is the type of the refer- ence, not the class of the current object denoted by the reference, that determines which variable will actually be accessed. CS211, Fall, 1999. KAM Object-oriented Programming 21/71 Overriding vs. Overloading • Method overriding requires the same method signature (name and parameters) and the same return type, and that the original method is inherited from its super- class. • Overloading requires different method signatures, but the method name should be the same. • To overload methods, the parameters must differ in type or number. • The return type is not a part of the signature, changing it is not enough to overload methods. • A method can be overloaded in the class it is defined in, or in a subclass of its class. • Invoking an overridden method in the superclass from a subclass requires special syntax (for example, the keyword super). CS211, Fall, 1999. KAM Object-oriented Programming 22/71 Object Reference super • The this reference is passed as an implicit parameter when an instance method is invoked. • It denotes the object on which the method is called. • The keyword super can be used in the body of an instance method in a subclass to access variables and invoke methods inherited from the superclass. • The keyword super provides a reference to the current object as an instance of its superclass. • The super.super.X construct is invalid. CS211, Fall, 1999. KAM Object-oriented Programming 23/71 Example 4 Using super Keyword // Exceptions class InvalidHoursException extends Exception {} class NegativeHoursException extends InvalidHoursException {} class ZeroHoursException extends InvalidHoursException {} class Light { protected String billType = "Small bill"; // (1) protected double getBill(int noOfHours) throws InvalidHoursException { // (2) double smallAmount = 10.0, smallBill = smallAmount * noOfHours; System.out.println(billType + ": " + smallBill); return smallBill; } public void banner() { // (3) System.out.println("Let there be light!"); } } CS211, Fall, 1999. KAM Object-oriented Programming 24/71 class TubeLight extends Light { public String billType = "Large bill"; // (4) Shadowing. public double getBill(final int noOfHours) throws ZeroHoursException { // (5) Overriding. double largeAmount = 100.0, largeBill = largeAmount * noOfHours; System.out.println(billType + ": " + largeBill); return largeBill; } public double getBill() { // (6) System.out.println("No bill"); return 0.0; } } class NeonLight extends TubeLight { // ... public void demonstrate() throws InvalidHoursException { // (7) super.banner(); // (8) super.getBill(20); // (9) super.getBill(); // (10) System.out.println(super.billType); // (11) ((Light) this).getBill(20); // (12) System.out.println(((Light) this).billType); // (13) } } CS211, Fall, 1999. KAM Object-oriented Programming 29/71 Example 5 this() Constructor Call class Light { // Instance Variables private int noOfWatts; private boolean indicator; private String location; // Constructors Light() { // (1) Explicit default constructor this(0, false); System.out.println("Returning from default constructor no. 1."); } Light(int watt, boolean ind) { // (2) Non-default this(watt, ind, "X"); System.out.println("Returning from non-default constructor no. 2."); } Light(int noOfWatts, boolean indicator, String location) { // (3) Non-default this.noOfWatts = noOfWatts; this.indicator = indicator; this.location = new String(location); System.out.println("Returning from non-default constructor no. 3."); } } CS211, Fall, 1999. KAM Object-oriented Programming 30/71 public class DemoThisCall { public static void main(String args[]) { // (4) System.out.println("Creating Light object no.1."); Light light1 = new Light(); // (5) System.out.println("Creating Light object no.2."); Light light2 = new Light(250, true); // (6) System.out.println("Creating Light object no.3."); Light light3 = new Light(250, true, "attic"); // (7) } } Output from the program: Creating Light object no.1. Returning from non-default constructor no. 3. Returning from non-default constructor no. 2. Returning from default constructor no. 1. Creating Light object no.2. Returning from non-default constructor no. 3. Returning from non-default constructor no. 2. Creating Light object no.3. Returning from non-default constructor no. 3. CS211, Fall, 1999. KAM Object-oriented Programming 31/71 super() Constructor Call • The super() construct is used in a subclass constructor to invoke constructors in the immediate superclass. • This allows the subclass to influence the initialization of its inherited state when an object of the subclass is created. • A super() call in the constructor of a subclass will result in the execution of the rel- evant constructor from the superclass, based on the arguments passed. • The super() call must occur as the first statement in a constructor, and it can only be used in a constructor definition. • This implies that this() and super() calls cannot both occur in the same con- structor. CS211, Fall, 1999. KAM Object-oriented Programming 32/71 Example 6 super() Constructor Call class Light { // Instance Variables private int noOfWatts; private boolean indicator; private String location; // Constructors Light() { // (1) Explicit default constructor this(0, false); System.out.println( "Returning from default constructor no. 1 in class Light"); } Light(int watt, boolean ind) { // (2) Non-default this(watt, ind, "X"); System.out.println( "Returning from non-default constructor no. 2 in class Light"); } Light(int noOfWatts, boolean indicator, String location) { // (3) Non-default super(); // (4) this.noOfWatts = noOfWatts; this.indicator = indicator; this.location = new String(location); System.out.println( "Returning from non-default constructor no. 3 in class Light"); } } CS211, Fall, 1999. KAM Object-oriented Programming 33/71 class TubeLight extends Light { // Instance variables private int tubeLength; private int colorNo; TubeLight(int tubeLength, int colorNo) { // (5) Non-default this(tubeLength, colorNo, 100, true, "Unknown"); System.out.println( "Returning from non-default constructor no. 1 in class TubeLight"); } TubeLight(int tubeLength, int colorNo, int noOfWatts, boolean indicator, String location) { // (6) Non-default super(noOfWatts, indicator, location); // (7) this.tubeLength = tubeLength; this.colorNo = colorNo; System.out.println( "Returning from non-default constructor no. 2 in class TubeLight"); } } public class Chaining { public static void main(String args[]) { System.out.println("Creating a TubeLight object."); TubeLight tubeLightRef = new TubeLight(20, 5); // (8) } } CS211, Fall, 1999. KAM Object-oriented Programming 34/71 Output from the program: Creating a TubeLight object. Returning from non-default constructor no. 3 in class Light Returning from non-default constructor no. 2 in class TubeLight Returning from non-default constructor no. 1 in class TubeLight CS211, Fall, 1999. KAM Object-oriented Programming 39/71 Interfaces • Java provides interfaces which allow new type names to be introduced and used polymorphically, and also permit multiple interface inheritance. • Interfaces support programming by contract. CS211, Fall, 1999. KAM Object-oriented Programming 40/71 Defining Interfaces • An interface defines a contract by specifying prototypes of methods, and not their implementation. <interface header> { <interface body> } • An interface is abstract by definition and therefore cannot be instantiated. It should also not be declared abstract. • Reference variables of the interface type can be declared. CS211, Fall, 1999. KAM Object-oriented Programming 41/71 Figure 3 Inheritance Relations StackImpl push() pop() ... SafeStackImpl isFull() isEmpty() ... IStack push() pop() ISafeStack isFull() isEmpty() Object «interface» «interface» CS211, Fall, 1999. KAM Object-oriented Programming 42/71 Example 7 Interfaces interface IStack { // (1) void push(Object item); Object pop(); } class StackImpl implements IStack { // (2) protected Object[] stackArray; protected int tos; public StackImpl(int capacity) { stackArray = new Object[capacity]; tos = -1; } public void push(Object item) // (3) { stackArray[++tos] = item; } public Object pop() { // (4) Object objRef = stackArray[tos]; stackArray[tos] = null; tos--; return objRef; } public Object peek() { return stackArray[tos]; } } CS211, Fall, 1999. KAM Object-oriented Programming 43/71 interface ISafeStack extends IStack { // (5) boolean isEmpty(); boolean isFull(); } class SafeStackImpl extends StackImpl implements ISafeStack { // (6) public SafeStackImpl(int capacity) { super(capacity); } public boolean isEmpty() { return tos < 0; } // (7) public boolean isFull() { return tos >= stackArray.length; } // (8) } public class StackUser { public static void main(String args[]) { // (9) SafeStackImpl safeStackRef = new SafeStackImpl(10); StackImpl stackRef = safeStackRef; ISafeStack isafeStackRef = safeStackRef; IStack istackRef = safeStackRef; Object objRef = safeStackRef; safeStackRef.push("Dollars"); // (10) stackRef.push("Kroner"); System.out.println(isafeStackRef.pop()); System.out.println(istackRef.pop()); System.out.println(objRef.getClass()); } } CS211, Fall, 1999. KAM Object-oriented Programming 44/71 Output from the program: Kroner Dollars class SafeStackImpl CS211, Fall, 1999. KAM Object-oriented Programming 49/71 Example 8 Variables in Interfaces interface Constants { double PI = 3.14; String AREA_UNITS = " sq.cm."; String LENGTH_UNITS = " cm."; } public class Client implements Constants { public static void main(String args[]) { double radius = 1.5; System.out.println("Area of circle is " + (PI*radius*radius) + AREA_UNITS); // (1) Direct access. System.out.println("Circumference of circle is " + (2*PI*radius) + Constants.LENGTH_UNITS); // (2) Fully qualified name. } } Output from the program: Area of circle is 7.0649999999999995 sq.cm. Circumference of circle is 9.42 cm. CS211, Fall, 1999. KAM Object-oriented Programming 50/71 Types in Java • Only primitive data and reference values can be stored in variables. • Arrays are objects in Java. • Array types (boolean[], Object[], StackImpl[]) implicitly augment the inheritance hierarchy. • All array types implicitly extend the Object class • Note the difference between arrays of primitive datatypes and class types. • Arrays of reference types also extend the array type Object[]. • Variables of array reference types can be declared, and arrays of reference types can be instantiated. • An array reference exhibits the same polymorphic behavior as any other refer- ence, subject to its location in the extended inheritance hierarchy. Corresponding Types: Primitive data values Primitive datatypes. Reference values Class, interface or array type (called reference types). Objects Class or array type. CS211, Fall, 1999. KAM Object-oriented Programming 51/71 Figure 4 Array Types in Inheritance Hierarchy ISafeStack[] IStack[] Object Object[]double[]boolean[] SafeStackImpl[] StackImpl[] ... «interface» «interface» CS211, Fall, 1999. KAM Object-oriented Programming 52/71 Assigning, Passing and Casting References • Reference values, like primitive values, can be assigned, cast and passed as argu- ments. • For values of the primitive datatypes and reference types, conversions occur dur- ing: • Assignment • Parameter passing • Explicit casting • The rule of thumb for the primitive datatypes is that widening conversions are permitted, but narrowing conversions require an explicit cast. • The rule of thumb for reference values is that conversions up the inheritance hier- archy are permitted (called upcasting), but conversions down the hierarchy require explicit casting (called downcasting). • The parameter passing conversion rules are useful in creating generic data types which can handle objects of arbitrary types. CS211, Fall, 1999. KAM Object-oriented Programming 53/71 Example 9 Assigning and Passing Reference Values interface IStack { /* See Example 7 for definition */ } class StackImpl implements IStack { /* See Example 7 for definition */ } interface ISafeStack extends IStack { /* See Example 7 for definition */ } class SafeStackImpl extends StackImpl implements ISafeStack { /* See Example 7 for definition */ } public class ReferenceConversion { public static void main(String args[]) { Object objRef; StackImpl stackRef; SafeStackImpl safeStackRef = new SafeStackImpl(10); IStack iStackRef; ISafeStack iSafeStackRef; // SourceType is a class type objRef = safeStackRef; // (1) Always possible stackRef = safeStackRef; // (2) Subclass to superclass assignment iStackRef = stackRef; // (3) StackImpl implements IStack iSafeStackRef = safeStackRef;// (4) SafeStackImpl implements ISafeStack // SourceType is an interface type objRef = iStackRef; // (5) Always possible iStackRef = iSafeStackRef; // (6) Sub- to super-interface assignment CS211, Fall, 1999. KAM Object-oriented Programming 54/71 // SourceType is an array type. Object[] objArray = new Object[3]; StackImpl[] stackArray = new StackImpl[3]; SafeStackImpl[] safeStackArray = new SafeStackImpl[5]; ISafeStack[] iSafeStackArray = new SafeStackImpl[5]; int[] intArray = new int[10]; objRef = objArray; // (7) Always possible objRef = stackArray; // (8) Always possible objArray = stackArray; // (9) Always possible objArray = iSafeStackArray; // (10) Always possible objRef = intArray; // (11) Always possible // objArray = intArray; // (12) Compile time error stackArray = safeStackArray; // (13) Subclass array to superclass array iSafeStackArray = safeStackArray; // (14) SafeStackImpl implements ISafeStack // Parameter Conversion System.out.println("First call:"); sendParams(stackRef, safeStackRef, iStackRef, safeStackArray,iSafeStackArray); // (15) // Call Signature: sendParams(StackImpl, SafeStackImpl, IStack, // SafeStackImpl[], ISafeStack[]); System.out.println("Second call:"); sendParams(iSafeStackArray, stackRef, iSafeStackRef, stackArray, safeStackArray); // (16) // Call Signature: sendParams(ISafeStack[], StackImpl, ISafeStack, // StackImpl[], SafeStackImpl[]); } CS211, Fall, 1999. KAM Object-oriented Programming 59/71 Polymorphism and Dynamic Method Lookup • Which object a reference will actually denote during runtime cannot always be determined at compile time. • Polymorphism allows a reference to denote different objects in the inheritance hierarchy at different times during execution. • Such a reference is a supertype reference. • When a method is invoked using a reference, the method definition which actu- ally gets executed is determined both by the class of the object denoted by the ref- erence at runtime and the method signature. • Dynamic method lookup is the process of determining which method definition a method signature denotes during runtime, based on the class of the object. • Polymorphism and dynamic method lookup form a powerful programming par- adigm which simplifies client definitions, encourages object decoupling and sup- ports dynamically changing relationships between objects at runtime. CS211, Fall, 1999. KAM Object-oriented Programming 60/71 Figure 5 Polymorphic Methods draw() Shape draw() Rectangle draw() Square draw() Circle draw() IDrawable draw() Map «interface» CS211, Fall, 1999. KAM Object-oriented Programming 61/71 Example 11 Polymorphism and Dynamic Method Lookup interface IDrawable { void draw(); } class Shape implements IDrawable { public void draw() { System.out.println("Drawing a Shape."); } } class Circle extends Shape { public void draw() { System.out.println("Drawing a Circle."); } } class Rectangle extends Shape { public void draw() { System.out.println("Drawing a Rectangle."); } } class Square extends Rectangle { public void draw() { System.out.println("Drawing a Square."); } } class Map implements IDrawable { public void draw() { System.out.println("Drawing a Map."); } } CS211, Fall, 1999. KAM Object-oriented Programming 62/71 public class PolymorphRefs { public static void main(String args[]) { Shape[] shapes = {new Circle(), new Rectangle(), new Square()}; // (1) IDrawable[] drawables = {new Shape(), new Rectangle(), new Map()};// (2) System.out.println("Draw shapes:"); for (int i = 0; i < shapes.length; i++) // (3) shapes[i].draw(); System.out.println("Draw drawables:"); for (int i = 0; i < drawables.length; i++) // (4) drawables[i].draw(); } } Output from the program: Draw shapes: Drawing a Circle. Drawing a Rectangle. Drawing a Square. Draw drawables: Drawing a Shape. Drawing a Rectangle. Drawing a Map. CS211, Fall, 1999. KAM Object-oriented Programming 63/71 Choosing between Inheritance and Aggregation • Choosing between inheritance and aggregation to model relationships can be a crucial design decision. • A good design strategy advocates that inheritance should be used only if the rela- tionship is-a is unequivocally maintained throughout the lifetime of the objects involved, otherwise aggregation is the best choice. • A role is often confused with an is-a relationship. • Changing roles would involve a new object to represent the new role every time this happened. • Code reuse is also best achieved by aggregation when there is no is-a relationship. • Aggregation with method delegating can result in robust abstractions. • Both inheritance and aggregation promote encapsulation of implementation, as changes to the implementation are localized to the class. • Changing the contract of a superclass can have consequences for the subclasses (called the ripple effect) and also for clients who are dependent on a particular behavior of the subclasses. CS211, Fall, 1999. KAM Object-oriented Programming 64/71 Achieving Polymorphism • Polymorphism is achieved through inheritance and interface implementation. • Code relying on polymorphic behavior will still work without any change if new subclasses or new classes implementing the interface are added. • If no obvious is-a relationship is present, then polymorphism is best achieved by using aggregation with interface implementation. CS211, Fall, 1999. KAM Object-oriented Programming 69/71 public class Client { // (5) public static void main(String args[]) { String string1 = "Queues are boring to stand in!"; int length1 = string1.length(); QueueByAggregation queue = new QueueByAggregation(); for (int i = 0; i<length1; i++) queue.enqueue(new Character(string1.charAt(i))); while (!queue.empty()) System.out.print((Character) queue.dequeue()); System.out.println(); String string2 = "!no tis ot nuf era skcatS"; int length2 = string2.length(); StackByInheritance stack = new StackByInheritance(); for (int i = 0; i<length2; i++) stack.push(new Character(string2.charAt(i))); stack.insertAtBack(new Character(’!’)); // (6) while (!stack.empty()) System.out.print((Character) stack.pop()); System.out.println(); } } Output from the program: Queues are boring to stand in! Stacks are fun to sit on! CS211, Fall, 1999. KAM Object-oriented Programming 70/71 Encapsulation • Encapsulation helps to make clear the distinction between an object’s contract and implementation. • Encapsulation has major consequences for program development. • Results in programs that are "black boxes". • Implementation of an object can change without implications for the clients. • Reduces dependency between program modules (hence complexity), as the internals of an object are hidden from the clients, who cannot influence its implementation. • Encourages code-reuse. CS211, Fall, 1999. KAM Object-oriented Programming 71/71 Encapsulation Levels Packages Classes MethodsData BlocksData Data