<Type, in Param>는 Generic 타입이라혹 하는데 Type은 그냥 어떤 타입을 가리키는 기호에 불과합니다. 예를 들면 List가 대표적인 Generic을 사용하는 클래스입니다. List<T>로 선언되어 있습니다. 여기서 T는 아무런 의미가 없어요. 그냥 어떤 타입이 올거라는 의미입니다. List안에 String 타입만 담고싶다면 List<String, Int만 담고 싶다면 List<Int>, Person클래스만 담고 싶다면 List<Person>으로 사용하시면 됩니다.
val stringList: List<String> = arrayListOf()
stringList.add("Hello world") (o)
stringList.add(99) (x) - compile error
Generic은 실제로는 타입이 정해져 있지 않고, 사용할 때 주어지는 타입을 사용하게 됩니다. 뒤의 Param도 마찬가지구요. 예를들면,
class MyUseCase: UseCase<String, Int>
class MyUseCase: UseCase<List<String>, Boolean>
처럼, 어떤 타입이든지 들어갈 수 있습니다. 그리고 in은 Param 타입의 하위 타입이라는 의미입니다. 예를 들면,
interface Expr<in T> {
fun eval(): T
}
Class NumberExpr: Expr<Number> {
override fun eval(): Double {
}
}
이렇게 하면, Double은 Number의 하위 타입이므로 사용이 가능합니다. Int, Float, Long 이런 타입들도 Number의 하위타입이므로 eval 함수의 리턴타입으로 사용할 수 있겠죠. out을 쓰면 그 반대구요.
Any는 모든 Class의 최상위 타입, 즉 Java Object type이라고 보시면 될 것 같구요. where 키워드를 사용하면 UseCase의 Type이 뭔지 모를 때 Type은 Any 타입이 된다고 알려주는 것입니다. 즉
abstract class UseCase<Type, in Param> where Type: Any {
abstract fun execute(P: Param): Type
}
class MyUseCase: UseCase<List<*>, String>() {
override fun execute(P: String): List<*> {
}
}
List<*>는 List<Any>로 간주됩니다. 그런데 님의 예제에서는 굳이 where절은 필요가 없어 보이네요.