You are correct that you cannot instantiate SomeInterface directly, but you can pass implementations of your interface to SomeClass. This way SomeClass can use someFunction() but doesn't care about the lower-level implementation details of the interface (aka polymorphism).
interface SomeInterface {
fun someFunction()
}
class SomeClass(private val someInterface: SomeInterface) {
fun doSomething() = someInterface.someFunction()
}
class SomeImplementation(): SomeInterface {
override fun someFunction() {
println("did something")
}
}
fun main() {
val someClass = SomeClass(SomeImplementation())
someClass.doSomething()
}