therealbluepandabear
03/02/2021, 5:20 AMfun main() {
val capitalsService: CapitalsService = CapitalsServiceImpl(CapitalsRepositoryImpl())
capitalsService.getCapitals()
}
interface CapitalsService {
fun getCapitals(): List<Capital>
}
class CapitalsServiceImpl(private val capitalsRepository: CapitalsRepository) : CapitalsService {
override fun getCapitals(): List<Capital> = capitalsRepository.getCapitals()
}
interface CapitalsRepository {
fun getCapitals(): List<Capital>
}
class CapitalsRepositoryImpl : CapitalsRepository {
override fun getCapitals() = listOf(Capital("Paris", Country("France", "Europe", 67399000), 2175601))
}
data class Country(val countryName: String?, val continent: String?, val population: Int?)
data class Capital(val cityName: String?, val capitalOf: Country?, val population: Int?)
Matteo Mirk
03/02/2021, 8:53 AMJoel
03/02/2021, 3:25 PMs/fun getCapitals(): List<Capital>/val capitals: List<Capital>
Part of the fun of Kotlin is that getters and setters are defined automagically. Your interfaces and objects have capitals
, and can be implemented as val capitals = listOf(...)
or`val capitals: List<Capital> get() = ...` if necessary.Iterable
over List
whenever possible, but that may change depending on context and whatever you're trying to achieve.Dmitry Kandalov
03/05/2021, 9:26 AMJoel
03/05/2021, 3:04 PMImpl
postfix? I've seen Default
prefix and IThing
as an interface name, but that feels odd.Matteo Mirk
03/05/2021, 3:20 PMCapitals
-> class: ConstantCapitals, HttpCapitals, FileCapitals
etc.Dmitry Kandalov
03/05/2021, 3:48 PMStubCapitalsRepository
, InMemoryCapitalsRepository
or DbCapitalsRepository
if it actually reads data from database. Another trick in Kotlin is to define invoke()
function in the companion object of interface and put default implementation there so you don’t need to come up with explicit name:
interface Foo {
fun bar()
companion object {
operator fun invoke() = object : Foo {
override fun bar() = 123
}
}
}