0% found this document useful (0 votes)
11 views82 pages

U04p1-Polymorphism - Final Java and Google and

The document outlines a lecture on Object-Oriented Programming focusing on polymorphism, abstract classes, and interfaces. It covers key concepts such as inheritance, the DRY principle, and various types of polymorphism including subtype and parametric polymorphism. Additionally, it provides practical examples and considerations for implementing these concepts in Java programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views82 pages

U04p1-Polymorphism - Final Java and Google and

The document outlines a lecture on Object-Oriented Programming focusing on polymorphism, abstract classes, and interfaces. It covers key concepts such as inheritance, the DRY principle, and various types of polymorphism including subtype and parametric polymorphism. Additionally, it provides practical examples and considerations for implementing these concepts in Java programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 82

Motivating OO -

Polymorphism
Prof Prairie
UNC COMP 301
Spring 25
Announcements
• Homework A01 is due on Sunday night at 11:59am.
 Late Days will begin accruing one hour later.
• Late days are integers. (2 hours late = 1 late day used.)

• You are responsible for making sure that the highest grade is “active” in
Gradescope
• The last block of office hours during the weekend is usually REALLY BUSY.
 Please plan ahead and do not procrastinate.
 Not getting into office hours is not an excuse to turn in work late.

• Midterm 1 next Wednesday


• Review Session! Sunday 4-6 in SN 0014
Last Time
• Inheritance!
• DRY Principle for leveling up your code.
 No, the autograder doesn’t check for this, but you should.

• Parent Classes
Today!
• Abstract classes
• Interfaces
• 4 types of polymorphism
Top Down Design
I have a category of items that will
share functionality.

If I don’t have a parent class, I may


have lots of if/switch statements that
call the same method in different
classes.

To maintain the DRY principle, I can


make a parent class.

This picture isn’t hugely relevant but I like it.


Identifying when to refactor

public static double calculateArea(DoubleTriangle triangle){


return triangle.getArea();
}
public static double calculateArea(PointTriangle triangle){
return triangle.getArea();
}
public static double calculateArea(Square square){
return square.getArea();
Identifying when to refactor

public static double calculateArea(Shape shape){


return shape.getArea();
}
package ShapeMaker.Shapes;

Considerations public class Shape {

• Area is not defined for a public Shape(){}


generic shape
}
• Two options:
• Leave it out public static double calculateArea(DoubleTriangle triangle){
return triangle.getArea();
}
public static double calculateArea(PointTriangle triangle){
return triangle.getArea();
}
public static double calculateArea(Square square){
return square.getArea();
package ShapeMaker.Shapes;

public class Shape {

Considerations public Shape(){}


• Area is not defined for a public double getArea(){
generic shape return -1; //This should never be called.
}
• Two options: }

• Leave it out
• Placeholder public static double calculateArea(Shape shape){
return shape.getArea();
• Parent classes must }}
contain all methods to be
used. (surprise surprise)
That can’t be right….
We are writing code that we want
to never be run?

There has to be a better way.


Abstract classes
(for the art lover)
Abstract Classes
• Abstract classes are parent classes that cannot be instantiated
independently.
 Only their children can be created with a constructor.

• Abstract methods are method headers with no bodies.


 Implementation is left to the children classes

• By Convention, starts with capital “AShape”


In Practice

package ShapeMaker.Shapes;

public abstract class AShape {

public Shape(){}

public abstract double getArea();


}
Where do interfaces fit?
AShape a = new Point(0, 0);

Interfaces vs Abstract Classes IShape i = new Point(5, 0);

Interfaces Abstract Classes


• class “implements” an interface • class “extends” an abstract class

• Contains Method headers with • Contains Method headers with


no bodies no bodies

• Can have default • Can have default


implementations implementations

• Used as a type in code outside • Used as a type in code outside


class class
An interface is a set of
An abstract class is a half-
requirements that guarantees
finished object.
functionality exists
Interfaces exist to solve the problem of
multiple inheritance

Person Employee
superclass Interface

Student Professor
subclass subclass
Interfaces exist to solve the problem of
multiple inheritance

Person Employee Comparable


superclass Interface

Student Professor
subclass subclass
Polymorphism
“Many forms”
Super Random Aside – “foo” and “bar” as
variable names
• When at all possible, use SOMETHING to create variable names that
have some connection to the usage.

• When something truly has no meaning, “foo” and “bar” are general
use nonsense variable names.
Object – The Mother Of All Classes
• All classes inherit from Object
 Top of the class hierarchy
 Implicit if no parent class is otherwise specified.

So when we say this: We are implicitly doing this:


public class MyClass { public class MyClass extends Object {
... ...
} }

 A variable typed as Object can hold anything.


• But then restricted to just the methods that are defined at the level of Object

 Public methods that all objects have:


• public boolean equals(Object o) <- but this probably doesn’t do what you want it to
• public String toString() <- this definitely doesn’t do what you want it to.
Super Random Aside – “foo” and “bar” as
variable names
It is possible that foobar is a playful allusion to the World War II-era military slang FUBAR (F***** Up Beyond All
Recognition).[4]

The first known use of the terms in print in a programming context appears in a 1965 edition of MIT's Tech
Engineering News.[9] The use of foo in a programming context is generally credited to the Tech Model Railroad
Club (TMRC) of MIT from c. 1960.[2] In the complex model system, there were scram switches located at numerous
places around the room that could be thrown if something undesirable was about to occur, such as a train moving
at full power towards an obstruction. Another feature of the system was a digital clock on the dispatch board. When
someone hit a scram switch, the clock stopped and the display was replaced with the word "FOO"; at TMRC the
scram switches are, therefore, called "Foo switches". Because of this, an entry in the 1959 Dictionary of the TMRC
Language went something like this: "FOO: The first syllable of the misquoted sacred chant phrase 'foo mane
padme hum.' Our first obligation is to keep the foo counters turning."[10] One book describing the MIT train room
describes two buttons by the door labeled "foo" and "bar". These were general-purpose buttons and were often
repurposed for whatever fun idea the MIT hackers had at the time, hence the adoption of foo and bar as general-
purpose variable names.

Wikipedia
Super Random Aside – “foo” and “bar” as
variable names
Foobar was used as a variable name in
the Fortran code of Colossal Cave
Adventure (1977 Crowther and Woods
version). The variable FOOBAR was used to
contain the player's progress in saying the
magic phrase "Fee Fie Foe Foo", a phrase
from an historical quatrain in the classic
English fairy tale Jack and the
Beanstalk. Intel also used the term foo in
their programming documentation in
1978.[12]
Poly • morph • ism

Many Forms

Polymorphism is the principle of reusing one common name


or symbol to refer to multiple different (related) entities
Types of polymorphism
1. Type polymorphism
 When an interface has multiple implementation classes
 When a class has multiple subclasses

2. Parametric polymorphism
 Using generics (<T>) so a field or variable can take on different data types

3. When multiple methods have the same name


 Method overriding (method is overridden in subclass)
 Method overloading (methods with same name but different arguments)

4. When one class has multiple constructors


 Constructor overloading (constructors with different arguments)
Polymorphism why?

Polymorphism allows programmers to program to a


specific subset of an object's members.

Polymorphism allows programmers to group


similar (but different) entities or behaviors together
and program to their common type.
When one type Is-a
instanceof another
Inheritance diagram
“Is-a” Person
relationships class
String getName()

Student Professor
subclass subclass
int getCredits() String getStatus()
void takeCredits(int credits) void promote()
String getStatus()

 Every Student is-a Person


 Every Professor is-a Person
 Not every Person is-a Student
 Not every Person is-a Professor

Rule: Every (subclass type) is-a (superclass type)


But not every (superclass type) is-a (subclass type)
Java’s instanceof operator
if (jane instanceof Professor) { In Java, instanceof is an operator
retval += "foo";
 Just like + (add) and – (subtract)
}
It takes 2 operands:
if (jane instanceof Student) { 1. A reference on the left
retval += "bar"; 2. A type on the right
}

It evaluates to true only if,


if (jane instanceof Person) { in memory, the reference
retval += "!"; “is an” instance of the type
}
return retval;
Example
Student hanna = new Student("hanna");
This program’s output:
if (hanna instanceof Student) {
retval += "foo"; foobar
}

if (hanna instanceof Person) {


retval += "bar";
}
Poll Everywhere-p2
Person prg = new Professor(“Prairie");
Prompt: What will this
if (prg instanceof Professor) { program output?
retval += "foo";
}

if (prg instanceof Student) {


retval += "bar";
}

if (prg instanceof Person) {


retval += "!";
}
PollEv Take away: foo! You can mix inherited types at variable
declaration, and it will still recognize both types, because a Professor
ISA Person
Type casting
Type casting and “is-a”
Heap
program memory
prairie2
Professor
instance
prairie1 “is-a” Professor in prairie1
memory, so the reference can be Person
instance
type cast
name

status 0

Person prairie1 = new Professor("prairie"); String


instance
Professor prairie2 = (Professor) prairie1;
k m p
Type casting and “is-a”
Heap
program memory
prairie1
Professor
instance
prairie2
Person
instance
name

status 0

Professor prairie1 = new Professor("prairie"); String


instance
Person prairie2 = (Person) prairie1;
k m p

Professor prairie1 = new


Professor("prairie");
Person prairie2 =
prairie1;
Type casting and “is-a”
Heap
program memory
prairie1
Professor
instance
prairie2
Person
instance
name

Professor prairie1 = new status 0


Professor("prairie");
String
Person prairie2 = prairie1; instance
k m p

Person ichabod = new Person(“ichabod");


ichabod
Professor ichabod2 = (Professor) ichabod; Person
instance
name

String
ichabod is only a Person in instance

memory, so it can’t be type cast  a a r o n


Compile Time vs Runtime Type Checking
• Upcasts (implicit) can be checked at compile time.
 An upcast is one that the compiler can confirm (or deny) definitively using
the declared type relationships in the code.
 Because they can be checked, explicit casting is unnecessary.
Person prairie2 = prairie1;
// Same as: Person prairie2 = (Person) prairie1;

• Downcasts (Explicit) must be checked at runtime.


 The reference type may or may not be valid at the point when the line of
code is executed.
 If not, will result in a ClassCastException.
Is-A Relationships With Interfaces
class A implements InterA { A "is a" InterA

B “is a” A
B “is a” InterA
class B extends A implements InterB { B “is a” InterB
}

C “is a” A
C “is a” B
class C extends B implements InterC { C “is a” InterA
} C “is a” InterB
C “is a” InterC
Typecasting Inter
A
class A implements InterA { }
Prompt: Which lines can be
class B extends A implements InterB { } A implicitly typecast?
class C extends B implements InterC { }

/*********************************/ Inter
void foo (InterB x) { B
InterA x_as_ia = (InterA) x; // foo, line 1 www.pollev.com/profprairie
B x_as_b = (B) x; // foo, line 2
InterC x_as_ic = (InterC) x; // foo, line 3
B
}
Inter
void bar (B x) { C
InterA x_as_ia = (InterA) x; // bar, line 1
InterB x_as_ib = (InterB) x; // bar, line 2
InterC x_as_ic = (InterC) x; // bar, line 3
} C
Upcasts Are Usually Implicit
class A implements InterA { }
class A implements InterA {
...class B extends A implements InterB { }
}
class C extends B implements InterC { }

/*********************************/
void Bfoo
class (InterB A
extends x) implements
{ InterB {
... InterA x_as_ia = (InterA) x; // foo, line 1
B x_as_b = (B) x; // foo, line 2
} InterC x_as_ic = (InterC) x; // foo, line 3
}

void bar (B x) {
InterA x_as_ia = x; // bar, line 1
InterB
class x_as_ibB=implements
C extends x; // bar, line InterC
2 {
... InterC x_as_ic = (InterC) x; // bar, line 3
}
}
v
Method access
Inheritance diagram
Method access Person
class
String getName()

When calling a method on an


object, you have access only to Student Professor
subclass subclass
the methods defined for the
int getCredits() String getStatus()
declared type of the reference. void takeCredits(int credits) void promote()
String getStatus()

Declared type Accessible methods


Person getName()
Student getName(), getCredits(), takeCredits(), getStatus()
Professor getName(), getStatus(), promote()
Inheritance diagram
Method access Person
class
String getName()

When calling a method on an


object, you have access only to Student Professor
subclass subclass
the methods defined for the
int getCredits() String getStatus()
declared type of the reference. void takeCredits(int credits) void promote()
String getStatus()

Person pat = new Student("pat");


So, which methods are
Even though object that pat accessible for pat?
references is a Student in memory,
the declared type of pat is Person Only getName()! A typecast
is necessary to access any
Student methods
Examples of polymorphism
1. Subtype polymorphism
 When an interface has multiple implementation classes
 When a class has multiple subclasses

2. Parametric polymorphism
 Using generics (<E>) so a field or variable can take on different data types

3. When multiple methods have the same name


 Method overriding (method is overridden in subclass)
 Method overloading (methods with same name but different arguments)

4. When one class has multiple constructors


 Constructor overloading (constructors with different arguments)
Parametric Polymorphism
Generic Type – A class or interface that
Generic types takes a data type as a parameter

This defines a type parameter named T to 1. Using angled brackets (<>) at the
act as a placeholder for a real data type end of the class name, declare a list of
type parameters to act as
public class Container<T> {
placeholders for real data types
private T contents;

public Container(T item) {


2. Use the type parameters as contents = item;
if they represented valid types }
throughout the class body
public T getContents() {
return contents;
}

public void setContents(T item) {


contents = item;
}
}
Generic Type – A class or interface that
Generic types takes a data type as a parameter

3. When creating an instance of the class,


use angled brackets again to fill in the type public class Container<T> {
private T contents;
parameter with a real reference type
public Container(T item) {
contents = item;
}
Container<String> name = new Container<>("Tuna");
Container<Double> price = new Container<>(1.67);
public T getContents() {
return contents;
System.out.println(name.getContents());
}
System.out.println(price.getContents());
public void setContents(T item) {
contents = item;
4. Now, name is a Container<String> }
}
which stores a String value…
…and price is a Container<Double> Once constructed, an instance’s type
which stores a Double value parameter(s) cannot be changed
Java generics

Doobi the Generic Flying Shark

• Let us write a class while leaving data type used inside it unbound
– Syntax uses diamond-braced suffix in declaration, e.g., class Node<E>
• E is then used inside the class as a placeholder for eventual concrete type
• Example, let’s make our Node class support generic values:
public class Node<E>{
private E value; // stored element is of type E
private Node<E> next; // next node reference
public Node(E value, Node<E> next){ this.value = value; this.next = next; }
public E getValue(){ return this.value; }
...
}
Java generics
• We don’t want separate Data Structures to hold just Strings, just
Ints, just Pets, etc.
– Otherwise we would need an implementation for every type of object (impossible)
– NodeString, NodeInt, NodePet, etc

• Generics let us have a “generic” implementation, that the


Constructor will specify upon creation.
• It’s a way of saying (“I don’t know what type, but I don’t care, as long
as they are all the same”

Node<Integer> intNode = new Node<Integer>(102);


int intVal = intNode.getValue(); // no type cast needed!

Node<String> strNode = new Node<String>("Waddy", intNode); // can’t mix types!
Examples of polymorphism
1. Subtype polymorphism
 When an interface has multiple implementation classes
 When a class has multiple subclasses

2. Parametric polymorphism
 Using generics (<E>) so a field or variable can take on different data types

3. When multiple methods have the same name


 Method overriding (method is overridden in subclass)
 Method overloading (methods with same name but different arguments)

4. When one class has multiple constructors


 Constructor overloading (constructors with different arguments)
Overriding methods
Overriding is an example of polymorphism
Overriding methods
Why bother to construct
prairie as a Professor in
memory if the reference is type
Person? This is called
method overriding
Person prairie = new Professor(“Prairie");

System.out.println(prairie.getName());

Let’s make getName()


return “Prof Prairie”
instead of just “Prairie”
Overriding methods class Professor extends Person {
private int status;

public Professor(String name) {


class Person { super(name);
private String name; status = 0;
}
public Person(String name) {
this.name = name; public void promote() {
} if (status == 2) {
throw new RuntimeException("Can't promote");
public String getName() { }
return name; status++; // Adds 1 to the value of status
} }
}
public String getStatus() {
if (status == 0) {
return "Assistant";
Imagine what would happen if } else if (status == 1) {
return "Associate";
we changed getName() directly } else {
in the Person class return "Full";
}
}
}
Overriding methods class Professor extends Person {
private int status;

public Professor(String name) {


class Person { super(name);
private String name; status = 0;
}
public Person(String name) {
this.name = name; public void promote() {
} if (status == 2) {
throw new RuntimeException("Can't promote");
public String getName() { }
return "Prof " + name; status++; // Adds 1 to the value of status
} }
}
public String getStatus() {
if (status == 0) {
return "Assistant";
Imagine what would happen if } else if (status == 1) {
return "Associate";
we changed getName() directly } else {
in the Person class return "Full";
}
}
Changing getName() here }
would affect Student too
Overriding methods
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
} else {
return "Full";
}
Override getName() inside }
the Professor class
@Override
public String getName() {
return "Prof " + name;
}
}
@Override directive
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
This funny line is called a return "Associate";
“compiler directive” } else {
return "Full";
}
}

@Override
public String getName() {
return "Prof " + name;
}
}
Field access
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
We’re not quite done! This return "Associate";
code won’t work. Why not? } else {
return "Full";
}
}
Two possible solutions:
@Override
1. Change private modifier public String getName() {
return "Prof " + name;
2. Use parent’s public getName() method }
instead of directly accessing name field }
Solution 1: Access modifier
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
private
} The member is only
accessible from
} inside the class body
protected The member is only
accessible from inside//the
status++; class
Adds 1 toand
thesubclasses
value of status
public String getName() { }
default
return name; The member is accessible from anywhere inside the package
}
}
public The member is accessible frompublic
anywhere
String getStatus() {
if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
} else {
return "Full";
}
}

@Override
public String getName() {
return "Professor " + name;
}
}
Solution 1: Access modifier
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
class Person { }
protected String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
} else {
return "Full";
Now it works because }
}

name is accessible inside


@Override
Professor public String getName() {
return "Professor " + name;
}
}
Solution 2: Superclass class Professor extends Person {
private int status;

getName() method public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
} else {
return "Full";
}
}

@Override
public String getName() {
return "Professor " + name;
}
}
Solution 2: Superclass class Professor extends Person {
private int status;

getName() method public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
This won’t work yet. } else {
return "Full";
Why not? }
}

@Override
public String getName() {
Recursion! return "Professor " + getName();
}
}
Solution 2: Superclass class Professor extends Person {
private int status;

getName() method public Professor(String name) {


super(name);
status = 0;
class Person { }
private String name;
public void promote() {
public Person(String name) { if (status == 2) {
this.name = name; throw new RuntimeException("Can't promote");
} }
status++; // Adds 1 to the value of status
public String getName() { }
return name;
} public String getStatus() {
} if (status == 0) {
return "Assistant";
} else if (status == 1) {
return "Associate";
} else {
Now it works! return "Full";
}
}

@Override
* super is just like this, except it public String getName() {
specifically refers to the superclass return "Professor " + super.getName();
}
portion of the object }
The final keyword
Is for more than just variables!
final keyword
class Professor extends Person {
private int status;
The final keyword indicates
immutability public Professor(String name) {
super(name);
status = 0;
When added to a method, }
final indicates that the method can // ...
never be overridden by subclasses
@Override
public final String getName() {
When added to a field or variable, return "Professor " + super.getName();
final indicates that its value cannot }
change after instantiation }

When added to a class,


final indicates that the class cannot
have subclasses
Overload (verb) – To define
more than one constructor or method
in a class with the same name

Overloading methods
Overloading is an example of polymorphism
Overloading methods Let’s overload the
promote() method by
class Professor extends Person {
private int status; adding a different version
of the same method
public Professor(String name) {
super(name);
status = 0;
}

public void promote() {


if (status == 2) {
throw new RuntimeException("Can't promote");
}
status++; // Adds 1 to the value of status
}

public void promote(int status) {


if (status < 0 || status > 2) {
throw new IllegalArgumentException("Invalid status");
}
this.status = status;
}
}
Overloading methods
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
} Must have a different number
of parameters or different
public void promote() { data types of parameters
if (status == 2) {
throw new RuntimeException("Can't promote");
} This is so the compiler can tell
status++; // Adds 1 to the value of status them apart and figure out
} which one to execute!
public void promote(int status) {
if (status < 0 || status > 2) {
throw new IllegalArgumentException("Invalid status");
}
this.status = status;
}
}
Overloading methods Overloaded methods need to
have the same access modifier
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
} They also need to have the same
static/non-static status
public void promote() {
if (status == 2) {
throw new RuntimeException("Can't promote");
}
status++; // Adds 1 to the value of status
}

public void promote(int status) {


if (status < 0 || status > 2) {
throw new IllegalArgumentException("Invalid status");
}
this.status = status;
}
}
Overloading methods The return type
of overloaded methods
class Professor extends Person {
private int status;
may or may not be different

public Professor(String name) {


super(name);
status = 0;
}
Overloaded methods can call
public void promote() { each other, but be careful of
if (status == 2) { recursion!
throw new RuntimeException("Can't promote");
}
status++; // Adds 1 to the value of status
}

public void promote(int status) {


if (status < 0 || status > 2) {
throw new IllegalArgumentException("Invalid status");
}
this.status = status;
}
}
Examples of polymorphism
1. Subtype polymorphism
 When an interface has multiple implementation classes
 When a class has multiple subclasses

2. Parametric polymorphism
 Using generics (<T>) so a field or variable can take on different data types

3. When multiple methods have the same name


 Method overriding (method is overridden in subclass)
 Method overloading (methods with same name but different arguments)

4. When one class has multiple constructors


 Constructor overloading (constructors with different arguments)
Overload (verb) – To define
more than one constructor or method
in a class with the same name

Overloading constructors
Overloading is an example of polymorphism
Overloading constructors Now let’s overload
the constructor!
class Professor extends Person {
private int status;

public Professor(String name) {


super(name);
status = 0;
}

public Professor(String name, int status) {


super(name);
this.status = status;
}
}
Overloading constructors Just like with overloaded
methods, overloaded
class Professor extends Person { constructors must have
private int status; different parameter lists
public Professor(String name) {
super(name); Must have a different number
status = 0; of parameters or different
} data types of parameters
public Professor(String name, int status) {
super(name); This is so the compiler can tell
this.status = status; them apart and figure out
} which one to execute!
}
Using overloaded constructors
The computer knows which
constructor to execute based
Professor kris = new Professor("Kris");
on the values passed in
Professor prairie = new
Professor("prairie", 0);

These do the same thing!

Professor kris = new Professor("Kris", 0);

Professor kris = new Professor("Kris");


Why overload?

It’s convenient!
Overloading allows you to make context-specific versions of a
constructor or method to perform the same action in different
situations

For example, supporting optional arguments


Chaining constructors
When one constructor calls a different, overloaded constructor
DRY - Chaining overloaded constructors
class Professor extends Person {
Notice how this
private int status;
constructor…
public Professor(String name) {
super(name);
status = 0; …is just a special case
} of this constructor
public Professor(String name, int status) {
super(name);
this.status = status;
}
}
Chaining overloaded constructors
class Professor extends Person {
private int status; Use this() to
call another constructor
public Professor(String name) {
this(name, 0);

public Professor(String name, int status) {


super(name);
this.status = status;
}
}
Chaining overloaded constructors
class Professor extends Person {
private int status; Use this() to
call another constructor
public Professor(String name) {
this(name, 0);
The compiler knows which
} constructor to execute based
on the values passed in
public Professor(String name, int status) {
super(name);
this.status = status;
}
}
Chaining overloaded constructors
class Professor extends Person {
private int status;
Just like with super(),
public Professor(String name) { this() must be the first
this(name, 0); line in the constructor
}

public Professor(String name, int status) {


You can always add other
super(name); code here, after the call to
this.status = status; this()
}

public Professor() {
this("Aaron");
}
}

You might also like