Operator overloading in Kotlin and how does this c

2019-09-02 21:21发布

问题:

I am reading the following code from a tutorial but I don't really get it.
Basically it tries to use operator overloading so that the following code works:

return today + YEAR * 2 + WEEK * 3 + DAY * 5  

What I understand:
This part:

operator fun MyDate.plus(timeInterval: TimeInterval): MyDate {   
    return addTimeIntervals(timeInterval, 1)  
} 

Enhances the class MyDate to support the + with a timeInterval so this would work myDate + YEAR for example.

This part:

operator fun MyDate.plus(timeIntervals: RepeatedTimeInterval) 
    = addTimeIntervals(timeIntervals.timeInterval, timeIntervals.number)  

Enhances the class MyDate to support * with a RepeatedInterval

This part just declares an empty class with 2 member variables timeInterval and number

class RepeatedTimeInterval(val timeInterval: TimeInterval, val number: Int)  

What I don't understand is how the multiplication is actually happening since RepeatedInterval is just an empty class.
Could someone please help my understand this?

import TimeInterval.*  

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)  

enum class TimeInterval { DAY, WEEK, YEAR }  

operator fun MyDate.plus(timeInterval: TimeInterval): MyDate {  
    return addTimeIntervals(timeInterval, 1)  
}  

class RepeatedTimeInterval(val timeInterval: TimeInterval, val number: Int)    
operator fun TimeInterval.times(number: Int) = RepeatedTimeInterval(this,   number)  



operator fun MyDate.plus(timeIntervals: RepeatedTimeInterval)   
    = addTimeIntervals(timeIntervals.timeInterval, timeIntervals.number)  




fun task1(today: MyDate): MyDate {    
    return today + YEAR + WEEK  
}  

fun task2(today: MyDate): MyDate {   
    return today + YEAR * 2 + WEEK * 3 + DAY * 5   
}  

Also this is part of the tutorial:

import java.util.Calendar  

fun MyDate.addTimeIntervals(timeInterval: TimeInterval, number: Int): MyDate {   
    val c = Calendar.getInstance()  
    c.set(year, month, dayOfMonth)  
    when (timeInterval) {  
        TimeInterval.DAY -> c.add(Calendar.DAY_OF_MONTH, number)  
        TimeInterval.WEEK -> c.add(Calendar.WEEK_OF_MONTH, number)  
        TimeInterval.YEAR -> c.add(Calendar.YEAR, number)  
    }  
    return MyDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH),   c.get(Calendar.DATE))  
}  

回答1:

YEAR * 2 is TimeInterval * Int. The compiler sees it isn't a built-in combination, so it looks for a method times marked as operator on TimeInterval which accepts Int (so e.g. TimeInterval.times(Int) or TimeInterval.times(Any)). This method can be a member of TimeInterval or an extension; there's absolutely no reason for it to be a member of RepeatedTimeInterval.

In fact, RepeatedTimeInterval doesn't have any part in resolving YEAR * 2 at all, it just happens to be the return type. Then today + YEAR * 2 is MyDate + RepeatedTimeInterval and the same rule is applied to pick operator fun MyDate.plus(timeIntervals: RepeatedTimeInterval) (and not operator fun MyDate.plus(timeInterval: TimeInterval) which is used for today + YEAR).

Note that with this code it isn't legal to have e.g. YEAR * 2 * 2; that would require RepeatedTimeInterval.times(Int) which again could be a member or an extension.



标签: kotlin