A Kotlin for loop can iterate through any object if the corresponding iterator member or extension function is available.
Make the class DateRange implement Iterable, so that it can be iterated over. Use the function MyDate.followingDate() defined in DateUtil.kt; you don't have to implement the logic for finding the following date on your own.
Use an object expression which plays the same role in Kotlin as an anonymous class in Java.
class DateRange(val start: MyDate, val end: MyDate)
fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
for (date in firstDate..secondDate) {
handler(date)
}
}
class DateRange(val start: MyDate, val end: MyDate) : Iterable<MyDate> {
override fun iterator() : Iterator<MyDate> {
// hasNext, next 구현이 되어야 됨
return object : Iterator<MyDate> {
var current: MyDate = start
override fun hasNext(): Boolean = current <= end
override fun next() : MyDate {
// 다음 요소가 없으면 예외 던지기
if(!hasNext()) throw NoSuchElementException()
val result = current
current = current.followingDate()
return result
}
}
}
}
fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
for (date in firstDate..secondDate) {
handler(date)
}
}
DateRange
클래스를 Iterable<MyDate>
로 구현하여 for
를 통해 처리를 반복할 수 있도록 만드는 문제이다.
Iterator
는 객체를 반복해서 읽어오는 객체다. 즉, 구현과 분리하여 처리를 반복하는 것이다.
Iterator
는 확인, 읽기 순으로 요소들을 읽어오기 때문에
hasNext()
를 통해 요소를 먼저 확인하고 next()
를 통해 값을 읽어와야 한다.
먼저 hasNext()
를 오버라이드 한다. <=
연산자를 이용해서 요소를 확인한다.
MyDate
클래스가 Comparable<MyDate>
인터페이스를 구현하고 있으므로 두 날짜 객체를 비교할 수 있기 때문이다. <=
연산자는 compareTo
메서드를 통해 두 날짜 객체를 비교하여 현재 날짜가 마지막 날짜보다 작거나 같은지를 확인한다.
그 다음으로 next()
를 오버라이드한다.
hasNext()
가 없다면 다음에 읽어올 요소가 없다는 뜻이므로 예외를 던지도록 한다.
current
는 현재 반복 중인 요소를 나타내고,result
는 현재 요소를 저장하여 next()
메서드가 호출된 후 반환할 값을 보관한다.최종적으로 result
를 반환하게 되면 next()
메서드가 호출될 때마다 현재 요소를 반환하고, 다음 요소로 업데이트할 수 있다.