Romance can be cast up to Fiction, Book, Object. Fiction can be cast up to Book and Object
Everything can basically be cast into an Object since everything inherits from that
Upcasting
Upcasting will always work without any errors (no need for if conditions or anything)
You lose out on the all the variables and methods from the cast you convert from. For example going from Fiction to Book you will still have access to all of Book's variables and methods, but not the ones that exist in Fiction that don't exist in Book
Romance prideAndPrejudice = new Romance();
Fiction f = prideAndPrejudice; // Upcast Romance -> Fiction
Object o = f; // Upcast Fiction -> Book
Downcasting
Downcasting is the opposite, going down the inheritance chain.
May cause errors without proper checking.
Doing this gives access to variables and methods of the new converted class.
Downcasting
Check if possible using variable instanceof Class
Use type casting operator (ClassName) before a variable to downcast.
Romance prideAndPrejudice = new Romance();
Object o = prideAndPrejudice;
if (o instanceof Fiction) { // if you don't check you _may_ get an error
Fiction f = (Fiction) o; // downcast
}
Downcasting with Flow Typing
Flow typing is a fancy syntax for type casting.
This code is equivalent to the last slide.
You can add a new variable name of the converted type like variable instanceof ClassName newVar and newVar is of type ClassName if it true.
Romance prideAndPrejudice = new Romance();
Object o = prideAndPrejudice;
if (o instanceof Fiction f) { // check + downcast// ...
}
Problem (10 minutes)
Convert the following program using up and down casts.
Be careful of the inheritance chain and when to use instanceof (and add if conditions when required)
publicclassTransport{ }
publicclassFourWheelsextendsTransport{ }
publicclassSedanextendsFourWheels{ }
publicclassBikeextendsTransport{ }
publicclassSUVextendsFourWheels{ }
SUV s = new SUV();
FourWheels f = new Sedan();
Bike b = new Bike();
Transport st = null; // convert s to transport
Sedan sd = null; // convert f to Sedan
Object o = null; // convert b to Object
Equals
Default methods and equals use cases
In java all objects by default have toString(), hashCode() and equqls(Object o)
They're not often that good so we override them to work as we want using @Override
For all objects we use equals() and for all primitives/null we use ==
Equals - algorithm
Check if null
Check if correct type using instanceof
Downcast it to the right type and then check all instance variables using a mix of == and equals()
Don't forget @Override
Problem (10 minutes)
For the class Movie (given next slide) create boolean equals(Object o) that checks the name of the movie and year of release to check for equality.
publicclassMovie{
private String name;
privateint year;
publicMovie(String setName, int setYear){
name = setName;
year = setYear;
}
}
var movie1 = new Movie("Spiderman", 2000);
var movie2 = new Movie("Spiderman", 2012);
var movie3 = new Movie("Spiderman", 2000);
System.out.println(movie1.equals(null));
System.out.println(movie2.equals(movie1));
System.out.println(movie1.equals(movie3));
Calling other constructors
super, this etc.
Super
super is used to refer to the parent class we inherit from.
You can also use it to call parent class methods super.equals(), super.calulateTip() etc. but you don't see that very often. Mostly we use it for constructors.
In the first line of the constructor we can call super(arg1, arg2) to start with the parent constructor.
This
this refers to the current class itself.
instance varibales can also be referred to as this.name, this.age, but you don't see this too often either. Using this.name to get around variable hiding in setters is regarded as a bad practice.
You can use this(arg1, arg2) to call other constructors of the same class.
Problem (10 minutes)
There is a class Student that inherits from Person with variables name. Student has year which can be Freshman, Junior etc.
Create a constructor Student(String name, String year)
Create another constructor Student(String name) which sets the default year as Freshman the first constructor.
publicclassPerson{
String name;
publicPerson(String setName){
name = setName;
}
}
publicclassStudentextendsPerson{
private String year;
// ...
}
var s = new Student("Harsh Deep");
Solutions
Spoilers
1
publicclassTransport{ }
publicclassFourWheelsextendsTransport{ }
publicclassSedanextendsFourWheels{ }
publicclassBikeextendsTransport{ }
publicclassSUVextendsFourWheels{ }
SUV s = new SUV();
FourWheels f = new Sedan();
Bike b = new Bike();
Transport st = s; // convert s to transportif (f instanceof Sedan) {
Sedan sd = (Sedan) f; // convert f to Sedan
}
Object o = b; // convert b to Object
2
publicclassMovie{
private String name;
privateint year;
publicMovie(String setName, int setYear){
name = setName;
year = setYear;
}
@Overridepublicbooleanequals(Object o){
return (o != null && o instanceof Movie m
&& name.equals(m.name) && year == m.year);
}
}
3
publicclassPerson{
// ...
}
publicclassStudentextendsPerson{
private String year;
publicStudent(String setName, String setYear){
super(setName);
year = setYear;
}
publicStudent(String name){
this(name, "Freshman");
}
}
var s = new Student("Harsh Deep");