CS 199 EMP

Hosted by Jackie Chan and Akhila Ashokan

Topics: Upcasting and Downcasting Revisited, References, Shallow and Deep Copy

Today's Learning Objectives

  • Upcasting and Downcasting Revisited

  • References

  • Shallow and Deep Copy

Write code on the homepage or any playground on the site!
https://cs125.cs.illinois.edu/

Slides are on the course site!
https://cs199emp.netlify.app/

Upcasting and Downcasting Revisited

Think of climbing a ladder. The top of the ladder is the Object class.
Upcasting = going up the ladder

  • super easy to do and always possible, but you lose the methods and variables in the original class

Downcasting = going down the ladder

  • more complicated because you must check if instance of using instanceof

Upcasting and Downcasting Example

class Movie {
  private int generalRating; 
  public int getGeneralRating() {
    return generalRating; 
  }
}

class Romance extends Movie { 
  private int cheesyRating; 
  public int getcheesyRating() {
    return cheesyRating;
  }
  
}

Movie twilight = new Romance(); // upcasting example 
twilight.getcheesyRating(); // will this run?
twilight.getGeneralRating(); // will this run? 

Practice with Upcasting and Downcasting (5 minutes)

Use the Movie class from the previous slide.

(1) What's another class that could descend from Movie? What's a unique method it would have?

(2) Create an Movie object that is an instance of the child class you came up with in (1).

(3) Properly downcast the Movie object from (2) into an instance of your child class and have it call the unique function you came up with in (1).

Practice with Upcasting and Downcasting (10 minutes)

Create a method called vetVisit() that accepts a single Pet parameter and returns a String that is the type of visit. Depending on what kind of pet is passed in, the vet visit will change. You can assume that all Pets have a method called isRegular() which returns a boolean value indicating whether the pet is a regular. If the Pet is null or not one of the described ones, you should return null.

  • If the pet is a Dog and a regular, the visit will be a "Regular Grooming". If the pet is a Dog but not a regular, the visit will be a "Parasite Prevention Session".

  • If the pet is a Cat, the visit will be a "Cat Wellness Exam".

  • If the pet is a Hamster, the visit will be a "Dental Care Visit".

References - The Analogy

House: Address :: Object: Reference
Phone: Phone Number :: Object: Reference
Student: UIN :: Object: Reference

A new object is created with the new keyword. Variables store references to that object. References can point to objects or nothing at all (null).

String jet = new String("My Private Jet");
String plane = jet; 
String anotherPlane = jet;
//How many objects do we have here?
// How many references do we have here?

More on References in Java

Changes are visible to all references

public class Student {
  String name = "akhila";
}
Student one = new Student();
Student two = one; // what is two.name? 
two.name = "jackie"; // what is one.name?

Pop Quiz: Does copying a reference copy the object?

Reference vs Instance Equality

public class Student {
  private String value;
  public Student(String setValue) {
    value = setValue;
  }
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Student)) {
      return false;
    }
    Student other = (Student) o;
    return value == other.value; 
  }
}
Student a = new Student("jackie");
Student b = new Student("jackie");
Student c = a;
System.out.println(a == b);       //`==` tests reference equality.
System.out.println(a.equals(b));  //`.equals()` tests instance equality.
System.out.println(a == c);
System.out.println(a.equals(c));

Practice with References (5 minutes)

Create a method called compareMovie() that takes in two Movies. If the references to the two movie objects are the same, it should return a String "passedTest1". If the instances of the two objects match, return a String "passedTest2". Otherwise, return "failed".

Starter Code

public class Movie {
  private String value;
  public Movie(String setValue) {
    value = setValue;
  }
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Movie)) {
      return false;
    }
    Movie other = (Movie) o;
    return value == other.value; 
  }
  
  public static String compareMovie(Movie first, Movie second) { 
    // write your code here 
  }
}

Java and Copying

Problem: Java has no built-in way to create a copy of a object (side note: clone() does exist, but it's not really recommended)

Solution: Use copy constructors!

Copy Constructors - conventions or a pattern adopted by Java programmers over time to copy objects

Shallow Copy - copy over references to the original object, but no new object is created...what does this mean???

Deep Copy - creates a whole new object that is a replica of the original

The Copy Constructor

public class Movie {
  int rating; 
  
  public Movie(int setRating) {
    rating = setRating; 
  }
  
  // copy constructor 
  public Movie(Movie o) {
    rating = o.rating; 
  }
}

Movie one = new Movie(2);
Movie two = new Movie(one);
System.out.println(two.rating);

Shallow Copy

Shallow Copy

Deep Copy

Deep Copy

Practice with Deep Copy (10 minutes)

Create a deep copy of the class below.

public class Playlist {
  private String[] playlist; 
  
  public Playlist(String[] songs) {
    playlist = songs;
  }

  //write your copy constructor here
}

String[] songs = {"Dear John", "22", "cardigan"};
Playlist one = new Playlist(songs);
Playlist second = new Playlist(one);

Yay! You made it to the end!

Recap:

  • Upcasting is easy. Downcasting is a little more complex.

  • References point to the object. Like your address points to your house.

  • With shallow copies, no new object is created. With deep copies, a new object is created.

Have a good week. See you on Friday. Peace ✌️

Solutions Section

Practice with Upcasting and Downcasting

class Movie {
  private int generalRating; 
  public int getGeneralRating() {
    return generalRating; 
  }
  
}

// new child class 
class International extends Movie {  
  private int language; 
  public int getLanguage() {
    return language;
  }
}

Movie parasite = new International();
if (parasite instanceof International) {
  International parasiteMovie = (International) parasite;
  parasiteMovie.getLanguage();
}

Practice with Upcasting and Downcasting

public class Pet {
  boolean isRegular() {
    return true;
  }
}

public class Dog extends Pet { }
public class Cat extends Pet { }
public class Hamster extends Pet { }

public String vetVisit(Pet p) {
  if (p instanceof Dog) {
    if (p.isRegular()) {
      return "Regular Grooming";
    } else {
      return "Parasite Prevention Session";
    }
  }
  if (p instanceof Cat) {
    return "Cat Wellness Exam";
  }
  if (p instanceof Hamster) {
    return "Dental Care Visit";
  }
  return null; 
}

Practice with References

public class Movie {
  private String value;
  public Movie(String setValue) {
    value = setValue;
  }
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Movie)) {
      return false;
    }
    Movie other = (Movie) o;
    return value == other.value; 
  }
  
  public static String compareMovie(Movie first, Movie second) {
    if (first == second) { // reference equality check
      return "passedTest1";
    } else if (first == null || second == null) {
      return "failed";
    } else if (first.equals(second)) {  // instance equality check 
      return "passedTest2";
    } else {
      return "failed";
    }
  }
}
Movie a = new Movie("jackie");
Movie b = new Movie("jackie");
Movie c = a;
Movie d = null;
Movie e = new Movie("akhila");

System.out.println(Movie.compareMovie(a, b)); // returns passedTest2
System.out.println(Movie.compareMovie(a, c)); // returns passedTest1
System.out.println(Movie.compareMovie(d, c)); // returns failed
System.out.println(Movie.compareMovie(a, e)); // returns failed

Practice with Deep Copy

  public Playlist(Playlist o) {
    playlist = new String[o.playlist.length];
    for (int i = 0; i < o.playlist.length; i++) {
      playlist[i] = o.playlist[i];
    } 
  }