---
marp: true
title: 20 October 2020
---

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

## <!-- fit --> Even More Practice

---

# <!-- fit --> Attendance Link:

https://forms.gle/8yto1LvJ4hntiKNu7

---

# 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 7 sessions for credit, attendence via google form.

---

# 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 --> Using interfaces

---

* Interfaces are like a set of rules for your class to follow.

* A list of functions and variables that a class has to implement.

* It doesn't give the functionality - unlike inheritance with `class`

* The goal is to create a way of making people implement common functionality.

---

# Syntax

* You can set type of variables with the name of the interface. `Comparable x = "harsh"` for example.

* Anything that `implements` an interface will have all the variables and methods the interface has which you can use.

* It can also be a datatype for a function parameter.

---

# Problem (10 minutes)

* Let's say we have an interface `Taxable` for a person who has to pay taxes.

* `Taxable` has a method `calculateTax()` which gives you their tax due.

* Get the sum of all the tax owed

---

```java
interface Taxable {
  double calculateTax();
}
public class Student implements Taxable {
  private double income;
  public Student(double setIncome) {
    income = setIncome;
  }
  // function implementations hidden
}

Student[] students = {new Student(1500), new Student(20), new Student(3999)};
```

---

# <!-- fit --> Implementing Interfaces

---

# Syntax

* When implementing an interface we declare a class and after it put the `implements` keyword

* Make sure to implement all the functions and variables listed

* Make sure to follow rules of `scope`. So if it requires some functions be `public` yours should be too. 

---

# Problem (10 minutes)

* Implement a the `Comparable` interface for the class `Student` to compare students on credit hours.

* Credit hours should be a instance variable of type `int[]` like `{3, 3, 4, 1, 3}`

* Use `assert` for making sure the other type is a `Student`

---

```java
public class Student implements Comparable {
  private int[] creditHours;
  public Student(int[] setHours) {
    creditHours = setHours;
  }
}

var s1 = new Student(new int[]{1, 1, 1});
var s2 = new Student(new int[]{4});
assert (s2.compareTo(s1) > 0);
```

---

# <!-- fit --> Lambda expressions

---

# Lambdas

* Lambdas are basically mini functions you can assign to variables

* They might seem kind of annoying and esoteric at the moment but when used with collections or `Android` they're very useful.

* Functional Programming: A different paradigm of programming language (different from OOP) where the basis of the structure of a program isn't objects/classes but functions and data types.

* Now days, lots of languages offer FP features within them like Python, Javascript, Java, Kotlin, C++ etc. 

* There also exist functional only languages you'll learn about in later classes. It's kind of like a different way of thinking.

---

# Syntax

The syntax is a bit tricky compared to normal functions.

1. Create an interface with the return type and params.

2. Declare a variable with the Interface you just made.

3. Assign the variable as `InterfaceName mary = (x, y, z) -> { ... }`

4. Note that you don't mention types here because we can get it from the interface definition. 

5. You can't use `var` in this case.
---

# Interface

```java
interface AreaInterface {
  double area(double a);
}
```

---

# Declare

```java
interface AreaInterface {
  double area(double a);
}

AreaInterface circle;
AreaInterface square;
```

---

# Create Lambdas

```java
AreaInterface circle = (radius) -> {
  var area = 3.14 * radius * radius; 
  return area;
};

AreaInterface square = (side) -> side * side;
// single line syntax you don't need to mention return or {}
```

---

# Use with dot notation

```java
interface AreaInterface {
  double area(double a);
}

AreaInterface circle = (radius) -> {
  var area = 3.14 * radius * radius; 
  return area;
};
AreaInterface square = (side) -> side * side;

System.out.println(circle.area(10));
System.out.println(square.area(5));
```

---

# Why not just functions?

* Compared to functions this might seem complex but.

* Sometimes we make lots of lambdas that follow the same signature so the code is smaller.

* Lots of times the `interface` that we used is already defined elsewhere, like when using buttons or web requests.

* Also useful on lists, but you won't be tested on this yet. I'll show an example on the next slide where you can see that it's pretty useful. The syntax might seem weird but basically lambdas allow you to chain lots of operations one after each other using lambdas.

---

```java
import java.util.Arrays;

String[] myArray = new String[]{"amirtha", "daniel", "rima", "davis"};
String[] newArray = Arrays.stream(myArray) // convert to a new type of data called Stream
                          .filter(s -> s.length() >= 5) // remove short names
                          .map(s -> s.toUpperCase()) // make each upper case
                          .toArray(String[]::new); // back to String[]
for (var s: newArray) {
  System.out.println(s);
}
// don't worry if you don't fully understand the syntax yet
```

---

# Problem (10 minutes)

* Create a mini test code for checking a function `int add(int a, int b)`

* Mixing interfaces and lambdas

* Write test cases to check scenarios for the add function and give each unique titles too

* One case has been provided, try writing 4-5 other ones

---

# Starter code

```java
interface TestCase {
  boolean test();
}
// print title if case fails
void checkCase(String title, TestCase t) {
  if (t.test() == false) {
    System.out.println("Failed: " + title);
  }
}
int add(int a, int b) {
  return a + b;
}
checkCase("Adding nothing gives the same number", () -> add(5, 0) == 5);
```

---

# <!-- fit --> Solutions

Spoilers

---

### 1)

```java
interface Taxable {
  double calculateTax();
}
public class Student implements Taxable {
  private double income;
  public Student(double setIncome) {
    income = setIncome;
  }
  public double calculateTax() {
    return 0.15 * income;
  }
}
Student[] students = {new Student(1500), new Student(20), new Student(3999)};
var sum = 0.0;
for (var s: students) {
  sum += s.calculateTax();
}
```

---

```java
  public int compareTo(Object o) {
    assert o instanceof Student;
    var ownGrades = 0;
    for (var hours: creditHours) {
      ownGrades += hours;
    }
    
    Student other = (Student) o;
    var otherGrades = 0;
    for (var hours: other.creditHours) {
      otherGrades += hours;
    }
    if (ownGrades > otherGrades) {
      return 1;
    } else if (ownGrades == otherGrades) {
      return 0;
    } else {
      return -1;
    }
  }
```

---

```java
interface TestCase {
  boolean test();
}

// print title if case fails
void checkCase(String title, TestCase t) {
  if (t.test() == false) {
    System.out.println("Failed: " + title);
  }
}
int add(int a, int b) {
  return a + b;
}

checkCase("Adding nothing gives the same number", () -> add(5, 0) == 5);
checkCase("It works with negative numbers", () -> add(5, -1) == 4);
checkCase("Order doesn't matter", () -> add(-1, 5) == 4);
checkCase("Two zeroes gives zero", () -> add(0, 0) == 0);
// example of a failing case due to error
checkCase("Two numbers of absolute signs gives 0", () -> add(5, -5) == 1);
```