intro to cs – honors i inheritance and polymorphism georgios portokalidis [email protected]
TRANSCRIPT
Why Inheritance? You can define or use a generic class
Later, you can define a more a specialized class that inherits the properties of the generic class
Persons in StevensWhat kind of properties
are shared by all persons?What kind of properties are shared by students?
public class Person{
private String name;public Person(){
name = "No name yet";}public Person(String initialName){
name = initialName;}public void setName(String newName){
name = newName;}public String getName(){
return name;}public void writeOutput(){
System.out.println("Name: " + name);}public boolean hasSameName(Person otherPerson){
return this.name.equalsIgnoreCase(otherPerson.name);}
}
Students in Stevens All students are persons
All students have a student number
We want a class that inherits all properties of a person but includes a student number
The class Student inherits all public methods and attributes of Person
◦ It can add its own instance variables and methods
public class Student extends Person{
private int studentNumber;
public int getStudentNumber(){
return studentNumber;}public void setStudentNumber(int
newStudentNumber){
studentNumber = newStudentNumber;}
}Can I access Person’s name? Private is private!
Using Derived Classes
public class InheritanceDemo{
public static void main(String[] args){
Student s = new Student();
s.setName("Warren Peace")s.setStudentNumber(1234);
}}
Which constructor is called?
This method is inherited
This method is only defined in Student
The default constructor of Student, which in turn by default invokes the default constructor of its base class
When to Use Inheritance If an is-a relationship does not exist between two proposed classes, do not use inheritance to derive one class from the other
It could be a has-a relationship◦ Define an object of one class as an instance variable within the other class
SYNTAXpublic class Derived_Class_Name extends Base_Class_Name{
Declarations_of_Added_Instance_VariablesDefinitions_of_Added__And_Changed_Methods
}
Using Derived Classes
public class InheritanceDemo{
public static void main(String[] args){
Student s = new Student();
s.setName("Warren Peace")s.setStudentNumber(1234);s.writeOutput();
}}
Invokes method of Person
Name: Warren Peace
Overridingpublic class Student extends Person{
…public void writeOutput() {
System.out.println("Name: " + getName());System.out.println("Student Number: " +
studentNumber);}
}
You can define a new method with the same heading which overrides the inherited one
Using Derived Classes
public class InheritanceDemo{
public static void main(String[] args){
Student s = new Student();
s.setName("Warren Peace")s.setStudentNumber(1234);s.writeOutput();
}}
Name: Warren PeaceStudent Number: 1234
Overriding is not Overloading
public class Person{
private String name;…public String getName(){
return name;}
}
public class Student extends Person{
…public String getName(String
title) {
return title + getName();
}}
public class Student extends Person{
…public char[] getName(String
title) {
return title + getName();
}}
Cannot override with the same signature and
different return type
Preventing Overridingpublic class Person{
private String name;…public final String
getName(){
return name;}
}
Final methods cannot be overriden
public final class Person{
private String name;…public final String
getName(){
return name;}
}
Final classes cannot be extended
How About Constructorspublic class Student extends Person{
private int studentNumber;
public Student(){
name = "No name yet";studentNumber = 0;
}public Student(String initialName, int
initialNumber){
setName(initialName);studentNumber = InitialNumber;
}}
What’s bad with this?
public class Student extends Person{
private int studentNumber;
public Student(){
super();studentNumber = 0;
}public Student(String initialName, int
initialNumber){
super(initialName);studentNumber = InitialNumber;
}}
Call the constructor of the parent/base class
super() behaves as this(). Must be the first action in
the constructor Call the constructor of the parent/base class
How About Constructorspublic class Student extends Person{
private int studentNumber;
public Student(){
studentNumber = 0;}public Student(String initialName, int
initialNumber){
studentNumber = InitialNumber;
}}
The default constructor is always called if super() is missing
What is the value of an object’s instance variables after using these
constructors?
Use super to Refer to the Base Class
public class Student extends Person{
…public void writeOutput() {
System.out.println("Name: " + super.getName());System.out.println("Student Number: " +
studentNumber);}
}
Use super to Call Overridden Methods
public class Student extends Person{
…public void writeOutput() {
System.out.println("Name: " + super.getName());super.writeOutput();
}}
Beware of Overriding vs Overloading
public class Person{
private String name;
public void reset(String newName) {
name = newName;}
}
public class Student extends Person{
private int studentNumber;
public void reset(String newName, int newNumber)
{setname(newName);name = newName;
}}
Java SE 8 is introducing annotations@Override can be used to force the compiler to produce an error if you are not actually overriding a method
@Override
Multiple Inheritancepublic class Person{
…}
public class Student extends Person{
…}
public class Undergraduate extends Student{
…}
public Undergraduate(){
super.super.writeOutput();}
Not possible
Type Compatibility An Undergrad is a Student is a Person
public class SomeClass{
public static void compareNumbers(Student s1, Student s2){
if (s1.getStudentNumber() == s2.getStudentNumber())
System.out.println(s1.getName() + " has the same " + "number as " + s2.getName());
elseSystem.out.println(s1.getName() + " has a
different“ + "number than " +
s2.getName());}. . .
}
Student studentObject = new Student("Jane Doe", 1234);Undergraduate undergradObject =
new Undergraduate("Jack Buck", 1234, 1);SomeClass.compareNumbers(studentObject, undergradObject);
Type Compatibility Note that this is not automatic type casting
An object can have multiple types◦ An Undergrad is also of the type Student and Person
The reverse is not true◦ A Person is not always a Student◦ Nor a Student always an Undergrad
The Object Class Java has an “Eve” class that is the ancestor of every class
Every class you write implicitly “extends” Object
public class SomeClass extends Object
{
…
}
You can write methods that take an Object type as parameter that will accept any object◦ Can I pass a primitive type to such methods?
Every class inherits toString() and equals() from Object◦ Do not expect these to work properly
Type Casting to Successor Classes
Example: overriding the defaults equals method
◦ public boolean equals(Object otherObject)
We could declare public boolean equals(Student otherStudent)
What is the problem with this?
To override we need to declare public boolean equals(Object otherObject){
Student otherStudent = (Student)otherObject;return this.hasSameName(otherStudent) &&(this.studentNumber ==
otherStudent.studentNumber);}
Different headings mean we are overloading
Type Casting to Successor Classes
Student oneStudent, otherStudent;
…
if (oneStudent.equals(otherStudent))
{
…
}
public boolean equals(Object otherObject){
Student otherStudent = (Student)otherObject;return this.hasSameName(otherStudent) &&(this.studentNumber ==
otherStudent.studentNumber);}
How can this go bad?
String notAStudent;
…
if (oneStudent.equals(notAStudent))
…
This will cause a run-time error, since the error cannot be detected at compile time
The instanceof Operatorpublic boolean equals(Object otherObject){
boolean isEqual = false;if ((otherObject != null) &&
(otherObject instanceof Student)){
Student otherStudent = (Student)otherObject;isEqual = this.sameName(otherStudent) &&
(this.studentNumber == otherStudent.studentNumber);}return isEqual;
}
SYNTAXObject instanceof Class_Name
Returns true if the object is of type Class_Name
Multiple Inheritance
ClassA ClassB
ClassC
Object
public class ClassA extends Object {
public void doSomething(){
System.out.println("doSomething implementation of A"); } //ClassA own method public void methodA(){ }
} public class ClassB extends Object {
public void doSomething(){
System.out.println("doSomething implementation of B"); } //ClassB own method public void methodB(){ }
} public class ClassC extends ClassB, ClassA{
public void test(){
doSomething();}
}
Which method will be called?
It is impossible to decide which method to call. Java avoids the diamond problem by
disallowing multiple inheritance
Polymorphism “Polymorphism allows you to make changes in the method definition for the derived classes and have those changes apply to the methods written in the base class.”
Person[] people = new Person[4];
people[0] = new Undergraduate("Cotty, Manny", 4910);people[1] = new Undergraduate("Kick, Anita", 9931);people[2] = new Student("DeBanque, Robin", 8812);people[3] = new Undergraduate("Bugg, June", 9901);
for (Person p: people){
p.writeOutput();System.out.println();
}
Let’s use a for-each loop to print all Persons information
Which writeOutput() will be called?
Even though we are using object references of type Person the methods of the child-class
objects are called
In Java this is called dynamic binding or late binding
Polymorphism REMEMBER Objects Know How They Are Supposed to Act
◦ The method that is to be called is determined at run time, and it does not depend on an the type of an object reference but the actually object
Java always assumes late binding◦ Some other languages allow you to control which methods will use late binding