---
marp: true
title: 6 October 2020
---

# <!-- fit --> CS 199 EMP

## <!-- fit --> 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

---

# <!-- fit --> Polymorphism Casting

---

# Upcasting

```java
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`

```java
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.

```java
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.

```java
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)

---

```java
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
```

---

# <!-- fit --> 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.

---

```java
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));
```

---

# <!-- fit --> 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.

---

```java
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");
```

---


# <!-- fit --> Solutions

Spoilers

---

1 

```java
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

```java
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

```java
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");
```