CS 199 EMP

Even More Practice

2 meetings every week Tuesday and Thursday

  • Early CST - Early risers and Eastern timezones

  • Evening CST - Western timezones (and really late Eastern folks)

  • Calendar contains zoom links

  • Attend 10 ones for credit.

Format

  • 3 practice problems every session

  • focused on practical understanding of concepts covered recently in class

  • slides and material available after class

How to follow along

  • Small breakout rooms of working together

  • Work for 10-15 minutes together, feel free to use paper, whiteboards, online share tools.

  • Use the code playground on the 125 homepage for the interactive running

Polymorphism Casting

Upcasting

public class Book { }
public class Fiction extends Book { }
public class Romance extends Fiction { } 
  • Up casting is going up the inheritance chain.

  • 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

  1. Check if possible using variable instanceof Class

  2. 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)

public class Transport { }
public class FourWheels extends Transport { }
public class Sedan extends FourWheels { }
public class Bike extends Transport { }
public class SUV extends FourWheels { }

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

  1. Check if null

  2. Check if correct type using instanceof

  3. Downcast it to the right type and then check all instance variables using a mix of == and equals()

  4. 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.

public class Movie {
  private String name;
  private int year;
  public Movie(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.

public class Person {
  String name;
  public Person(String setName) {
    name = setName;
  }
}

public class Student extends Person {
  private String year;
  // ...
}

var s = new Student("Harsh Deep");

Solutions

Spoilers

1

public class Transport { }
public class FourWheels extends Transport { }
public class Sedan extends FourWheels { }
public class Bike extends Transport { }
public class SUV extends FourWheels { }

SUV s = new SUV();
FourWheels f = new Sedan();
Bike b = new Bike();
Transport st = s; // convert s to transport
if (f instanceof Sedan) {
  Sedan sd = (Sedan) f; // convert f to Sedan
}

Object o = b; // convert b to Object

2

public class Movie {
  private String name;
  private int year;
  public Movie(String setName, int setYear) {
    name = setName;
    year = setYear;
  }
  
  @Override
  public boolean equals(Object o) {
    return (o != null && o instanceof Movie m 
      && name.equals(m.name) && year == m.year);
  }
}

3

public class Person {
  // ...
}

public class Student extends Person {
  private String year;
  public Student(String setName, String setYear) {
    super(setName);
    year = setYear;
  }
  public Student(String name) {
    this(name, "Freshman");
  }
}

var s = new Student("Harsh Deep");