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
Generics
classCounter<T>(privatevalvalue: T){
varcount=0
privateset
funadd(newValue: T){
if(value==newValue){
count++
}
}
}
valcounter=Counter(4)
assert(counter.count==0)
counter.add(4)
assert(counter.count==1)
counter.add("test")// fails
In this lesson we’ll examine Kotlin generics.
This is an advanced topic, but one that you are bound to encounter as you continue to use Kotlin.
Generics also allow the compiler to better check our code—and we always want that.
So let’s do this!
valthird=listOf<String>()// another empty List<String>
Remember: runtime errors cause things to fail right in the user’s face.
This is not good!
Compiler errors, in contrast, must be caught in development.
So transforming runtime errors to compiler errors helps us produce more correct programs.
This is good!
Because Kotlin knows what is stored in the list, it knows what we can and can’t
do with the list contents:
OK—so now we know how to use classes that accept type parameters.
But how about using the in our own classes?
This turns out to not be too hard!
Let’s explore together.
To start, let’s design a class that does not support type parameters,
but can still accept any object by using Any:
classLastN{
}
Next, let’s look at how to add a generic type parameter to our example above.
This will allow the compiler to ensure that all of the values added to LastN are the same type!
There are a few important things to understand about how Kotlin compiles generic classes.
First, the type parameter is not a variable.
You can use them in most places that you would normally use a type, but you can’t assign to them:
classExample<E>{
varvalue: E? =null
funtest(){
E=String// But you can't reassign a type parameter
value=E()// Also doesn't work, since maybe E doesn't have an empty constructor?
}
}
One useful way to think about what happens when your program is compiled is that the compiler replaces the type parameters with types used in your code.
So, given this generic class:
classExample<E>(valvalue: E)
If I create a Example<String>, it’s almost as if I had written this code:
You may have noticed above that when we implemented LastN we used a List rather than an array.
That wasn’t an accident!
Let’s see why and what problems arise with generic arrays.
You regularly see generic type parameters in Kotlin documentation.
Now that we’ve discussed a bit about how to use type parameters in our own code, we’re more prepared to understand documentation for classes that use them.
Let’s look at one familiar example together and discuss how to identify and interpret these type parameters.
Homework Restricted to Current CS 124 Students
A publicly-accessible version of this content is available at learncs.online.
Homework: BinaryTree Balanced
Created By: Geoffrey Challen
/ Version: 2020.11.0
Let's determine if a binary tree is height balanced.
A tree is height balanced if the height of any node's two subtrees (right and left) never differ by more than 1.
Provide a method named isBalanced.
isBalanced accepts a BinaryTree<*> and returns true if the tree is balanced, and false otherwise.
A few hints on this problem:
Your main entry point method will probably need to start the recursion using a private helper method, because the
main method doesn't accept nullable trees which you want to handle as a valid base case in your recursion
This helper method will probably have the same arguments as the main method, so you'll need to change something
else to make sure that the method signature is different and the compiler can determine which one you want to use
You will probably need a second helper method implementing tree height that you call in your primary recursive
method