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
interfaceTaxable{
doublecalculateTax();
}
publicclassStudentimplementsTaxable{
privatedouble income;
publicStudent(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
publicclassStudentimplementsComparable{
privateint[] creditHours;
publicStudent(int[] setHours){
creditHours = setHours;
}
}
var s1 = new Student(newint[]{1, 1, 1});
var s2 = new Student(newint[]{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.
Create an interface with the return type and params.
Declare a variable with the Interface you just made.
Assign the variable as InterfaceName mary = (x, y, z) -> { ... }
Note that you don't mention types here because we can get it from the interface definition.
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
interfaceAreaInterface{
doublearea(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
interfaceTestCase{
booleantest();
}
// print title if case failsvoidcheckCase(String title, TestCase t){
if (t.test() == false) {
System.out.println("Failed: " + title);
}
}
intadd(int a, int b){
return a + b;
}
checkCase("Adding nothing gives the same number", () -> add(5, 0) == 5);
Solutions
Spoilers
1)
interfaceTaxable{
doublecalculateTax();
}
publicclassStudentimplementsTaxable{
privatedouble income;
publicStudent(double setIncome){
income = setIncome;
}
publicdoublecalculateTax(){
return0.15 * income;
}
}
Student[] students = {new Student(1500), new Student(20), new Student(3999)};
var sum = 0.0;
for (var s: students) {
sum += s.calculateTax();
}
publicintcompareTo(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) {
return1;
} elseif (ownGrades == otherGrades) {
return0;
} else {
return -1;
}
}
interfaceTestCase{
booleantest();
}
// print title if case failsvoidcheckCase(String title, TestCase t){
if (t.test() == false) {
System.out.println("Failed: " + title);
}
}
intadd(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);