KotlinCS 124 LogoJava
PrevIndexNext
Kotlin
Java
  • Implementing a Map : 04/26/2024

  • map-reduce-filter : 04/25/2024

  • Generics : 04/24/2024

  • Hashing : 04/23/2024

  • Binary Search : 04/22/2024

  • MP3: Course Ratings : 04/19/2024

  • Quicksort : 04/18/2024

  • Merge Sort : 04/17/2024

  • Sorting Algorithms : 04/16/2024

  • MP Debugging Part 1 : 04/15/2024

  • MP2: Course Activity : 04/12/2024

  • Practice with Recursion : 04/11/2024

  • MP Debugging Part 0 : 04/10/2024

  • MP2: API Client : 04/09/2024

  • MP2: API Server : 04/08/2024

  • Trees and Recursion : 04/05/2024

  • Trees : 04/04/2024

  • Recursion : 04/03/2024

  • MP1: Filtering and Search : 04/02/2024

  • MP1: Loading and Sorting : 04/01/2024

  • Lists Review and Performance : 03/29/2024

  • Linked Lists : 03/28/2024

  • Algorithms and Lists : 03/27/2024

  • Continuing MP0 : 03/26/2024

  • Getting Started with MP0 : 03/25/2024

  • Lambda Expressions : 03/22/2024

  • Anonymous Classes : 03/21/2024

  • Practice with Interfaces : 03/20/2024

  • Implementing Interfaces : 03/19/2024

  • Using Interfaces : 03/18/2024

  • Working with Exceptions : 03/08/2024

  • Throwing Exceptions : 03/07/2024

  • Catching Exceptions : 03/06/2024

  • References and Polymorphism : 03/05/2024

  • References : 03/04/2024

  • Data Modeling 2 : 03/01/2024

  • Equality and Object Copying : 02/29/2024

  • Polymorphism : 02/28/2024

  • Inheritance : 02/27/2024

  • Data Modeling 1 : 02/26/2024

  • Companion Objects : 02/23/2024

  • Encapsulation : 02/22/2024

  • Constructors : 02/21/2024

  • Objects, Continued : 02/20/2024

  • Introduction to Objects : 02/19/2024

  • Compilation and Immutability : 02/16/2024

  • Practice with Collections : 02/15/2024

  • Maps and Sets : 02/14/2024

  • Lists and Type Parameters : 02/13/2024

  • Imports and Libraries : 02/12/2024

  • Multidimensional Arrays : 02/09/2024

  • Practice with Strings : 02/08/2024

  • null : 02/07/2024

  • Algorithms and Strings : 02/06/2024

  • Strings : 02/05/2024

  • Functions and Algorithms : 02/02/2024

  • Practice with Functions : 02/01/2024

  • More About Functions : 01/31/2024

  • Errors and Debugging : 01/30/2024

  • Functions : 01/29/2024

  • Practice with Loops and Algorithms : 01/26/2024

  • Algorithms : 01/25/2024

  • Loops : 01/24/2024

  • Arrays : 01/23/2024

  • Compound Conditionals : 01/22/2024

  • Conditional Expressions and Statements : 01/19/2024

  • Operations on Variables : 01/18/2024

  • Variables and Types : 01/17/2024

  • Welcome to CS 124 : 01/16/2024

Using Interfaces

interface Math {
fun add(first: Int, second: Int): Int
fun subtract(first: Int, second: Int): Int
}
class Mathematical : Math {
override fun add(first: Int, second: Int) = first + second
}
// Can you fix the compilation error?

This topic is one of the most important we’ll cover this semester! Maybe we’ve said that before? But we really mean it this time. Interfaces are everywhere in computer science, and Kotlin provides a great way to start understanding what they are and how they work. So let’s do it!

abstract
abstract

But first, a short but important digression into one of the Kotlin keywords that we have not yet covered: abstract. (Break out your Kotlin keyword bingo cards!) Like final, abstract can be applied to both classes and methods, with somewhat different results. Let’s explore together:

// Demonstrate how to use abstract

We’ll return to abstract in a minute. But for now let’s move on!

Interfaces
Interfaces

This lesson focuses on interfaces. Like references, interfaces are ubiquitous in computer science. But let’s look at the Wikipedia definition together:

In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information. The exchange can be between software, computer hardware, peripheral devices, humans, and combinations of these. Some computer hardware devices, such as a touchscreen, can both send and receive data through the interface, while others such as a mouse or microphone may only provide an interface to send data to a given system.

Every Object Has An Interface
Every Object Has An Interface

Just to be clear—while interfaces have a specific meaning in Kotlin that we’re exploring, every Kotlin object has an interface. Let’s see how:

class Course(val department: String, val number: String)

Limitations of Inheritance
Limitations of Inheritance

As we’ve pointed out in the past, Kotlin objects can only inherit from one class. This can lead to some problems as we design our classes.

Let’s consider a real example: natural ordering. Some classes has a natural ordering, meaning that there is a well-established order. For example:

However, not every class has such an ordering. For example, it’s not clear that the Pet classes we’ve been creating have a natural ordering.

So this is an example of a feature that not every Kotlin object has, meaning that we shouldn’t add it to Any. But whether or not an object can implement this feature doesn’t seem like it should constrain what it extends. Where does that leave us?

interface
interface

Kotlin interfaces provide a way for classes to declare that they support certain functionality. Unlike inheritance, a single class can implement more than one interface, while still extending another class. Let’s see how this works!

interface Simple {
fun simple(first: Int): Int
}

interface References
interface References

Reference variables work similarly with classes that implement interfaces as they do with polymorphism and inheritance. Let’s look at an example:

interface Simple {
fun simple(first: Int): Int
}

Remember abstract?
Remember abstract?

We can achieve something similar to interfaces using abstract, but it’s not quite the same. Let’s examine the differences:

interface Simple {
fun simple(first: Int): Int
}

Comparable
Comparable

As we begin with interfaces, we’ll focus on using them first, and then discuss more about how to provide existing interfaces. Let’s look at one example of a useful built-in Kotlin interface: Comparable.

OurComparable
OurComparable

Kotlin’s Comparable interface is inherited from Java, as is what is called a parameterized interface. We’ve discussed type parameters previously, but we don’t want to tangle with them on interfaces quite yet. So, instead, when we work with Comparable we’ll use our own version called OurComparable:

interface OurComparable {
fun compareTo(other: Any): Int
}

This works identically to the official Comparable interface except without the type parameter.

Ordering Operators Call compareTo
Ordering Operators Call compareTo

Remember that when we implemented .equals, Kotlin would call it when comparing two objects for equality using the == operator:

class Example(val value: Int) {
override fun equals(other: Any?): Boolean {
println("Example.equals called")
return when {
other?.javaClass != javaClass -> false
else -> {
other as Example
other.value == value
}
}
}
}
val first = Example(4)
val second = Example(8)
println(first == second)

Well, it turns out that if we implement compareTo Kotlin will also call it when comparing two objects for order using operators like <! We just have to do a bit more work to set up the method correctly. Let’s see how!

class Example(value: Int)
val first = Example(4)
val second = Example(8)
println(first < second)

OurComparable Example
OurComparable Example

Now, let’s write some code together that uses the OurComparable interface to make an existing (simple) algorithm more generic.

interface OurComparable {
fun compareTo(other: Any): Int
}
fun returnLarger(first: Int, second: Int): Int {
}

Practice: OurComparable Max

Created By: Geoffrey Challen
/ Version: 2021.3.0

Create a method named max. max should accept an array of objects that implement OurComparable and return the maximum. Require that the array be non-empty.

As a reminder, compareTo returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the passed object. Kotlin also allows you to use comparison operators directly with classes that implement compareTo. OurComparable works exactly the same as the official Comparable interface, except it is slightly simplified and does not accept a type parameter.

Practice: OurComparable Is Sorted

Created By: Geoffrey Challen
/ Version: 2021.10.0

Create a method named isSorted. isSorted accepts a list of OurComparables and returns true if the list is sorted in ascending order and false otherwise. If the passed list is empty you should throw an IllegalArgumentException.

As a reminder, compareTo returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the passed object. OurComparable works exactly the same as the official Comparable interface, except it is slightly simplified and does not accept a type parameter.

Homework: Compare GeoPoints

Created By: Geoffrey Challen
/ Version: 2022.10.0

One of the great things about interfaces is that we can use them to add common information to a variety of different classes where it might be appropriate. In this case, latitude and longitude information, broadly useful since many of the things we might want to model in our programs have a location on the Earth.

In this problem we'll write a so-called comparator method, which functions similarly to the Comparable interface, but instead of being called on one instance, is a static method that accepts two parameters of the same type. Create a method named compare that accepts two parameters that implement the IGeoPoint interface, defined as follows:

Return -1, zero, or 1 as the first argument is less than, equal to, or greater than the second. Compare the IGeoPoints based on their longitude values only, from smallest to largest. In addition, consider two IGeoPoints within 0.00000001 of each other (measured in terms of their longitude value) as equal.

More Practice

Need more practice? Head over to the practice page.