S10 Polymorphism
S10 Polymorphism
9-Oct-21
Signatures
n In any programming language, a signature is what
distinguishes one function or method from another
n In C, every function has to have a different name
n In Java, two methods have to differ in their names
or in the number or types of their parameters
n foo(int i) and foo(int i, int j) are different
n foo(int i) and foo(int k) are the same
n foo(int i, double d) and foo(double d, int i) are
different
n In C++, the signature also includes the return type
n But not in Java!
2
Polymorphism
n Polymorphism means many (poly) shapes (morph)
n In Java, polymorphism refers to the fact that you can
have multiple methods with the same name in the same
class
n There are two kinds of polymorphism:
n Overloading
n Two or more methods with different signatures
n Overriding
n Replacing an inherited method with another having the same signature
3
Overloading
class Test {
public static void main(String args[]) {
myPrint(5);
myPrint(5.0);
}
static void myPrint(int i) {
System.out.println("int i = " + i);
}
static void myPrint(double b) { // same name, different parameters
System.out.println("double d = " + d);
}
}
int i = 5
double d = 5.0
4
Why overload a method?
n So you can use the same names for methods that do essentially the same thing
n Example: println(int), println(double), println(boolean), println(String), etc.
n So you can supply defaults for the parameters:
int increment(int amount) {
count = count + amount;
return count;
}
int increment() {
return increment(1);
}
n Notice that one method can call another of the same name
n So you can supply additional information:
void printResults() {
System.out.println("total = " + total + ", average = " + average);
}
void printResult(String message) {
System.out.println(message + ": ");
printResults();
}
5
DRY (Don’t Repeat Yourself)
n When you overload a method with another, very similar method,
only one of them should do most of the work:
void debug() {
System.out.println("first = " + first + ", last = " + last);
for (int i = first; i <= last; i++) {
System.out.print(dictionary[i] + " ");
}
System.out.println();
}
void debug(String s) {
System.out.println("At checkpoint " + s + ":");
debug();
}
6
Another reason to overload methods
n You may want to do “the same thing” with different kinds of
data:
n class Student extends Person {
...
void printInformation() {
printPersonalInformation();
printGrades();
}
}
n class Professor extends Person() {
...
void printInformation() {
printPersonalInformation();
printResearchInterests();
}
}
n Java’s print and println methods are heavily overloaded
7
Legal assignments
class Test {
public static void main(String args[]) {
double d;
int i;
d = 5; // legal
i = 3.5; // illegal
i = (int) 3.5; // legal
}
}
n Widening is legal
n Narrowing is illegal (unless you cast)
8
Legal method calls
class Test {
public static void main(String args[]) {
myPrint(5);
}
static void myPrint(double d) {
System.out.println(d);
}
}
5.0
9
Illegal method calls
class Test {
public static void main(String args[]) {
myPrint(5.0);
}
static void myPrint(int i) {
System.out.println(i);
}
}
10
Java uses the most specific method
n class Test {
public static void main(String args[]) {
myPrint(5);
myPrint(5.0);
}
n static void myPrint(double d) {
System.out.println("double: " + d);
}
n static void myPrint(int i) {
System.out.println("int: " + i);
}
}
n int:5
double: 5.0
11
Multiple constructors I
n You can “overload” constructors as well as methods:
n Counter() {
count = 0;
}
Counter(int start) {
count = start;
}
12
Multiple constructors II
n One constructor can “call” another constructor in the
same class, but there are special rules
n You call the other constructor with the keyword this
n The call must be the very first thing the constructor does
n Point(int x, int y) {
this.x = x;
this.y = y;
sum = x + y;
}
n Point() {
this(0, 0);
}
n A common reason for overloading constructors is (as above)
to provide default values for missing parameters
13
Superclass construction I
n The very first thing any constructor does, automatically, is call
the default constructor for its superclass
n class Foo extends Bar {
Foo() { // constructor
super(); // invisible call to superclass constructor
...
n You can replace this with a call to a specific superclass
constructor
n Use the keyword super
n This must be the very first thing the constructor does
n class Foo extends Bar {
Foo(String name) { // constructor
super(name, 5); // explicit call to superclass constructor
...
14
Superclass construction II
n Unless you specify otherwise, every constructor calls the default constructor
for its superclass
n class Foo extends Bar {
Foo() { // constructor
super(); // invisible call to superclass constructor
...
n You can use this(...) to call another constructor in the same class:
n class Foo extends Bar {
Foo(String message) { // constructor
this(message, 0, 0); // your explicit call to another constructor
...
n You can use super(...) to call a specific superclass constructor
n class Foo extends Bar {
Foo(String name) { // constructor
super(name, 5); // your explicit call to some superclass constructor
...
n Since the call to another constructor must be the very first thing you do in the
constructor, you can only do one of the above
15
Shadowing
class Animal {
String name = "Animal";
public static void main(String args[]) {
Animal animal = new Animal();
Dog dog = new Dog();
System.out.println(animal.name + " " + dog.name);
}
}
public class Dog extends Animal {
String name = "Dog";
}
Animal Dog
n This is called shadowing—name in class Dog shadows
name in class Animal
16
Overriding
class Animal {
public static void main(String args[]) { n This is called
Animal animal = new Animal(); overriding a method
Dog dog = new Dog();
animal.print(); n Method print in Dog
dog.print(); overrides method
}
void print() {
print in Animal
System.out.println("Superclass Animal"); n A subclass variable
} can shadow a
}
superclass variable,
public class Dog extends Animal {
void print() { but a subclass method
System.out.println("Subclass Dog"); can override a
} superclass method
}
Superclass Animal
Subclass Dog
17
How to override a method
n Create a method in a subclass having the same signature
as a method in a superclass
n That is, create a method in a subclass having the same
name and the same number and types of parameters
n Parameter names don’t matter, just their types
n Restrictions:
n The return type must be the same
n The overriding method cannot be more private than the
method it overrides
18
Why override a method?
n Dog dog = new Dog();
System.out.println(dog);
n Prints something like Dog@feda4c00
n The println method calls the toString method, which is
defined in Java’s top-level Object class
n Hence, every object can be printed (though it might not look pretty)
n Java’s method public String toString() can be overridden
n If you add to class Dog the following:
public String toString() {
return name;
}
Then System.out.println(dog); will print the dog’s
name, which may be something like: Fido
19
More about toString()
n It is almost always a good idea to override
public String toString()
to return something “meaningful” about the object
n When debugging, it helps to be able to print objects
n When you print objects with System.out.print or System.out.println,
they automatically call the objects toString() method
n When you concatenate an object with a string, the object’s toString()
method is automatically called
20
Example
21
Example
class Shape{
void draw(){System.out.println("drawing...");}
}
class Rectangle extends Shape{
void draw(){System.out.println("drawing rectangle...");}
}
class Circle extends Shape{
void draw(){System.out.println("drawing circle...");}
}
class Triangle extends Shape{
void draw(){System.out.println("drawing triangle...");}
}
class ShapeTest{
public static void main(String args[]){
Shape s;
s=new Rectangle();
s.draw();
s=new Circle();
s.draw();
s=new Triangle();
s.draw();
}
}
22
n class Bank{
float getRateOfInterest(){return 0;} }
n class SBI extends Bank{
float getRateOfInterest(){return 8.4f;} }
n class ICICI extends Bank{
float getRateOfInterest(){return 7.3f;} }
n class AXIS extends Bank{
float getRateOfInterest(){return 9.7f;} }
class TestPolymorphism{
public static void main(String args[]){
Bank b;
b=new SBI();
System.out.println("SBI Rate of Interest: "+b.getRateOfInterest());
b=new ICICI();
System.out.println("ICICI Rate of Interest: "+b.getRateOfInterest());
b=new AXIS();
System.out.println("AXIS Rate of Interest: "+b.getRateOfInterest()); } }
Calling an overridden method
n When your class overrides an inherited method, it
basically “hides” the inherited method
n Within this class (but not from a different class), you
can still call the overridden method, by prefixing the
call with super.
n Example: super.printEverything();
n You would most likely do this in order to observe the
DRY principle
n The superclass method will do most of the work, but you add
to it or adjust its results
n This isn’t a call to a constructor, and can occur anywhere in
your class (it doesn’t have to be first)
24