Inheritance and Polymorphism Sahar Mosleh California State University San Marcos Page 1 Inheritance • It is one of the most important feature of object-oriented programs. • It allows creation of hierarchical classifications • You can create a general class and specific classes inherit the members of a general class • In java, the class that is inherited is called superclass • The class that is inheriting is called subclass • A subclass is a specialized version of a superclass Sahar Mosleh California State University San Marcos Page 2 Simple Inheritance Example class TwoDShape { doublewidth; doubleheight; void showDim() { System.out.println("Width and Height are " + width + " and " + height); }; } class Triangle extends TwoDShape { String style; double area() { return ((width*height) / 2.0); } } void showStyle() { System.out.println("Triangle is " + style); } Sahar Mosleh California State University San Marcos Page 3 class Shapes { public static void main(String args[ ]) { Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.width = 4.0; t1.height = 4.0; t1.style = "isosceles"; t2.width = 8.0; t2.height = 12.0; t2.style = "right"; Output -------Info for t1: Triangle is isosceles Width and Height are 4.0 and 4.0 Area is 8.0 Info for t2: Triangle is right Width and Height are 8.0 and 12.0 Area is 48.0 System.out.println("Info for t1: "); t1.showStyle(); t1.showDim(); System.out.println("Area is " + t1.area()); System.out.println(); } } System.out.println("Info for t2: "); t2.showStyle(); t2.showDim(); System.out.println("Area is " +t2.area()); System.out.println(); Sahar Mosleh California State University San Marcos Page 4 • The superclass is TwoDShape. • The subclass is Triangle. • The keyword that makes Triangle to inherit the members of TwoDShape is extends. • TwoDShape is a superclass because it defines the attributes of a “generic” two-dimensional shape such as Square, Triangle, and so on. • Then the Triangle class is a specific type of TwoDShape. Triangle class includes all members of TwoDShape class plus some specific member (attributes and methods) that is specific to objects of type Triangle. • Note that the attributes width and height do not belong to Triangle class but they are used in the method “area” since they are inherited by Triangle class. Sahar Mosleh California State University San Marcos Page 5 • The general form of a class declaration that inherits a superclass is: Class subclass-name extends superclass-name { // body } • Several subclasses may inherit from the same superclass • However, a subclass can only inherit from one superclass • This is similar to saying a parent can have many children but a child can only have one parent. • Subclasses of the same superclass are not related. The only common feature between them is what they inherit. Sahar Mosleh California State University San Marcos Page 6 class TwoDShape { double width; double height; void showDim() { System.out.println(“….”); }; } class Triangle extends TwoDShape { String style; double area() { …… } } Sahar Mosleh class Rectangle extends TwoDShape { boolean isSequence() { ….. } double area() { …… } } California State University San Marcos Page 7 • Triangle and Rectangle both inherit the attributes “width” and “height” and the method “showDim()” from the TwoDShape class • The method “area()” and attribute “style” belong specifically to Triangle class • Further, the methods “isSequence()” and “area()” (the one that is defined in Rectangle class) belongs to Rectangle class • The “area()” that is defined in Triangle class has nothing to do with the “area()” defined in Rectangle class. Sahar Mosleh California State University San Marcos Page 8 Member Access and Inheritance • Remember the rules of encapsulation property in objectoriented program • The rule is, a private member of a class can only be accessed through the methods of that class and not by members of other classes • The rule also applies for inheritance. It means when class B inherits the private members of class A, methods in class B do not allow to access private members inherited from class A. Sahar Mosleh California State University San Marcos Page 9 class TwoDShape { private double width; private double height; void showDim() { System.out.println("Width and Height are " + width + " and " + height); }; } class Triangle extends TwoDShape { String style; double area() { return ((width*height) / 2.0); } } Cannot access a private members of superclass void showStyle() { System.out.println("Triangle is " + style); } Sahar Mosleh California State University San Marcos Page 10 • To overcome this limitation, it is possible to create a set of accessor routines (get() and set() values) for the superclass private members in order to access them. class TwoDShape { private double width; private double height; double getWidth(){return width;} double getHeight(){return height;} void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } void showDim() { System.out.println("Width and Height are " + width + " and " + height);}; } class Triangle extends TwoDShape { String style; double area() { return ((super.getWidth()*(super.getHeight())) / 2.0); } } void showStyle() { System.out.println("Triangle is " + style); } Sahar Mosleh California State University San Marcos Page 11 class Shapes3 { public static void main(String args[ ]) { Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.setWidth(4.0); t1.setHeight(4.0); t1.style = "isosceles"; t2.setWidth(8.0); t2.setHeight(12.0); t2.style = "right"; Output -------Info for t1: Triangle is isosceles Width and Height are 4.0 and 4.0 Area is 8.0 Info for t2: Triangle is right Width and Height are 8.0 and 12.0 Area is 48.0 System.out.println("Info for t1: "); t1.showStyle(); t1.showDim(); System.out.println("Area is " + t1.area()); System.out.println(); } } System.out.println("Info for t2: "); t2.showStyle(); t2.showDim(); System.out.println("Area is " +t2.area()); System.out.println(); Sahar Mosleh California State University San Marcos Page 12 Constructors and Inheritance • It is possible for both subclasses and superclasses to have their own constructors • The question is that when an object of subclass is created which constructor is called? • Constructor of superclass is called? Or • Constructor of subclass is called? Or • Both constructors are called? • The answer is, when an object of the subclass is created, it has two portions: the specialized portion and the inherited portion. • The constructor of the superclass initializes the inherited attributes and the constructor of the subclass initializes the specialized attributes. But how? Sahar Mosleh California State University San Marcos Page 13 • In java, it is the job of the subclass constructor to invoke the superclass constructor • This is done through the keyword called “super”. (We will see an example of “super” shortly). • Therefore, if a subclass does not have any constructor, java simply invokes the default constructor of the subclasses and superclasses • When the superclass does not have constructor, only the constructor of the subclass is invoked and the default constructor of superclass is called • So the only interesting case is to understand the role of “super” keyword when both subclass and superclass define one or more constructors Sahar Mosleh California State University San Marcos Page 14 • The subclass can call a constructor defined by its superclass using the following statement super (parameter-list); where parameter-list specifies which constructor of the superclass should be called • Consider the next example: Sahar Mosleh California State University San Marcos Page 15 class TwoDShape { double width; double height; TwoDShape(double w, double h) { width = w; height = h; } } class Triangle extends TwoDShape { private String style; Triangle (String s, double w, double h) { super(w,h); style = s; } } class Shapes { public static void main(String args[ ]) { Triangle t1 = new Triangle(“isosceles”, 4.0, 4.0); Triangle t2 = new Triangle(“right”, 8.0,12.0); } } Sahar Mosleh California State University San Marcos Page 16 Using “super” to Access superclass Members • There is also another version of “super” that acts like the “this” keyword • The “this” keyword refers to the attributes specialized by the subclass and “super” refers to attributes inherited by the class • This is used as follows: super.member • When member is either a method or an attribute inherited by the class • This form of super is most applicable to situations in which member name of a subclass hides members by the same name in the superclass Sahar Mosleh California State University San Marcos Page 17 class A { int i; } class B extends A { int i; B (int a, int b) { super.i = a; i = b; } } void show() { System.out.println("i in superclass: System.out.println("i in subclass: } class useSuper { public static void main (String args[ ]) { B subOb = new B(1,2); subOb.show(); } } Sahar Mosleh " + super.i); " + i); Output -------- i in superclass: i in subclass: California State University San Marcos 1 2 Page 18 Method Overriding • When a method in a subclass has the same name and type signature as a method in its superclass, the method in the subclass is said to override the method inherited from its superclass • This is different from method overloading where methods have the same name but their signature (parameter list and return type) are different • When an overridden method is called from within a subclass, it will always refer to the version of the method defined by the subclass Sahar Mosleh California State University San Marcos Page 19 class A { int i, j; A(int a, int b) { i = a; j = b; } void show() { System.out.println("i and j: " + i + " " + j); } } class B extends A { int k; B(int a, int b, int c) { super(a, b); k = c; } void show() {System.out.println("k: " + k); } } class Override { public static void main (String args[ ]) { B subOb = new B(1, 2, 3); subOb.show(); // THIS CALLS B's SHOW() function } } Sahar Mosleh California State University San Marcos Page 20 • Note that when show() method is invoked on an object of type B, the version of show() inside B overrides the version in A • If you need to invoke the version of show() inherited in class B, you need to use the super operator super.show(); class B extends A { int k; B(int a, int b, int c) { super(a, b); k = c; } void show() { super.show(); // THIS CALLS A’s show() System.out.println("k: " + k); } } Sahar Mosleh California State University San Marcos Page 21 Polymorphism • Method overriding forms the basis for the concept of “Dynamic Method Dispatch” in java. • Dynamic Method Dispatch is the mechanism by which a call to an overridden method is resolved at run time rather than at compile time. • Java implements run-time polymorphism through Dynamic Method Dispatch. • When a reference object of a subclass is assigned to a reference object of its superclass, the overridden methods get polymorphic behavior. • This means, if through the object reference of the superclass an overridden method is called, java determines which version of that method to execute based on the type of object reference assigned to the object reference of the superclass. Sahar Mosleh California State University San Marcos Page 22 class ClassA { int x, y; void show() { System.out.println(“This is show() in superclass”);} } class ClassB extends ClassA { int z; void show() { System.out.println(“This is show() in subclass”);} } class Shapes { public static void main(String args[ ]) { ClassA objA = new ClassA(); objA.show(); ClassB objB = new ClassB(); objA = objB; objA.show(); } } Sahar Mosleh Output ---------This is show() in superclass This is show() in subclass California State University San Marcos Page 23 • After the statement ClassA objA = new ClassA(); objA.show(); • The show method in classA is called as expected. This is an example of non-polymorphic behavior because method invocation can be resolved at compile time • Now consider the following: ClassB objB = new ClassB(); objA = objB; objA.show(); • In this case, the objA reference takes the reference objB. Now the statement objA.show() will call the show() method overridden in ClassB. • This is an example of polymorphic behavior because method invocation is resolved at run time and not at compile time Sahar Mosleh California State University San Marcos Page 24 Abstract Methods and Abstract Classes • It is possible to create a superclass that only defines a generalized form that will be shared by all of its subclasses • Such a class should be declared as abstract • The abstract class determines the nature of the methods that the subclasses must implement but does not itself provide an implementation for some of its methods • We really should make a class as abstract if the class is unable to create a meaningful implementation for a method Sahar Mosleh California State University San Marcos Page 25 • Also, it is possible to make a method as an abstract method by specifying abstract type modifier. • An abstract method contains no body and therefore not implemented by the superclass • Therefore, a subclass must override it. It cannot simply use the version defined in the superclass • The general form of declaring an abstract method is: abstract type name (parameter-list); • Note that no body for the method is presented • The abstract method can only be applied to normal methods and not to static methods or constructors Sahar Mosleh California State University San Marcos Page 26 • To make a class abstract, we need to precede its class declaration with the abstract modifier. abstract class classA { …… } • It is not possible to create an object of an abstract class. • It is only possible to create object reference for an abstract class for the purpose of polymorphism • It is important to remember that when a subclass inherits an abstract class, it must implement all of the abstract methods in the superclass Sahar Mosleh California State University San Marcos Page 27 abstract class TwoDShape { private double width; private double height; private String name; TwoDShape() { width = height = 0.0; name = "null"; } TwoDShape(double w, double h, String n) {width = w; height = h; name = n;} double getWidth(){return width;} void setWidth(double w) { width = w; } double getHeight(){return height;}void setHeight(double h) { height = h; } void showDim() {System.out.println("Width and Height are " + width + " and " + height);}; abstract double area(); // Now area() is abstract } class Triangle extends TwoDShape { private String style; Triangle ( ) { super(); style = "null";} Triangle(String s, double w, double h){ super(w,h, "triangle"); style = s; } double area(){return (getWidth()*getHeight())/2.0;} } Sahar Mosleh California State University San Marcos Page 28 class AbsShape { public static void main(String args[ ]) { double TheArea; //THE NEXT STATEMENT PRODUCES COMPILE //ERROR BECAUSE IT IS NOT POSSIBLE TO INSTANTIATE //AN OBJECT FROM AN ABSTRACT CLASS /*TwoDShape shape = new TwoDShape(); */ TwoDShape shape1; //THIS IS OK. CAN CREATE a REFERENCE //TO AN ABSTRACT CLASS Triangle t1 = new Triangle("right", 8.0, 12.0); shape1 = t1; t1.showDim(); //showDim DOES NOT HAVE TO BE //OVERRIDDEN BECAUSE IT IS NOT abstract TheArea = shape1.area(); //ABSTRACT METHOD area() HAS TO //BE OVERRIDDEN BECAUSE IT IS AN //ABSTRACT METHOD System.out.println("The area of the triangle is: " + TheArea); } } Sahar Mosleh California State University San Marcos Page 29 Using Final • Although method overriding and inheritance are very powerful tools, in some occasions programmers may like to prevent them for some special classes. • For example, you may have a class that controls configuration of some hardware devices and you do not want any polymorphism attached to any methods of this class • Simply attach “final” modifier at the start of the class declaration final class classA { …. } Sahar Mosleh California State University San Marcos Page 30 • Further, methods declared as final cannot be overridden • Consider the following example: class classA { final void meth() { System.out.println(“This is a final method”); } } class classB extends ClassA { void meth() { // THIS PRODUCES COMPILE ERROR System.out.println(“illegal”); } } • Because meth() is declared final, it cannot be overridden in ClassB. If you attempt to do so, a compile-time error will result. Sahar Mosleh California State University San Marcos Page 31 • In general, by making a method to be a final method, we stop that method from being overridden. • If you make a class final, we stop that class from being inherited • If an attribute is declared final, that attribute is initialized at class level and its value cannot be changed Sahar Mosleh California State University San Marcos Page 32 class ErrMsg { final int OUTERR = 0; final int INERR = 1; final int DISKERR = 2; final int INDEXERR = 3; String msg[ ] = {"Output Error", "Input Error", "Disk Full", "Index Out-Of-Bounds"}; String getErrorMsg(int i) { if (i>=0 && i<msg.length) return msg[i]; else return "Invalid Error Code"; } } class FinalDemo2 { public static void main(String args[]) { ErrMsg err = new ErrMsg(); System.out.println(err.getErrorMsg(err.OUTERR)); System.out.println(err.getErrorMsg(err.DISKERR)); } } Sahar Mosleh California State University San Marcos Page 33