CS 199 EMP

Even More Practice

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

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

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)};

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

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

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

interface AreaInterface {
  double area(double a);
}

Declare

interface AreaInterface {
  double area(double a);
}

AreaInterface circle;
AreaInterface square;

Create Lambdas

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

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.

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

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

Solutions

Spoilers

1)

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();
}
  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;
    }
  }
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);