Hello, I can not understand thing with override. I have such interface:
interface ArithmeticOperations{
fun addition(num: Number): Double
fun subtraction(num: Number): Double
fun multiplication(num: Number): Double
fun division(num: Number): Double
}
I try to create class:
class Fractions(var integerPart: Long, var fractionalPart: Short) : ArithmeticOperations{
override fun addition(otherNum: Fractions): Double {
var result: Double = 0.0
result = abs(fractionalPart.toDouble()) + abs(otherNum.fractionalPart.toDouble())
return (abs(fractionalPart.toDouble()) + abs(otherNum.fractionalPart.toDouble()) +
integerPart.toDouble() + fractionalPart.toDouble())
}
}
And when i try override addition and add argument he says that function overrides nothing. Is there any sense in sush interface or it is more simple to just make those functions in class without interface? The purpoce of interface was that there is many types of numbers and operations for each is the same but type and some details are different and because of that we need to override functions.
This is the double-dispatch problem: The function to be invoked depends on the types of 2 variables instead of 1. But first an explanation of why your code does not compile.
addition(...) in Factions overrides nothing because its signature differs from the signature in the interface:
ArithmeticOperations: (Number) ->Double
Fractions: (Fractions) -> Double
Fractions will have to implement addition(Number). You can still add the overload addition(Fractions) if you want. The overload might be able to do things more efficiently because it handles 2 Fractions.
So how do you handle a situation like this? There are multiple possibilities:
You check the type of Number in each implementation of an arithmetic method. For example:
when (otherNum) {
is Fractions -> addFraction(otherNum)
is OtherType -> ...
is YetAnotherType -> ...
else -> // Some default implementation or an exception
}
Use the visitor pattern.
Simply convert all otherNums to a Double, and use that to do the calculation.
I like the idea, but to be honest I can’t think of any function that expects Number as a parameter. The fact is that Number is simply not usefull except for casting it to any of the other “base numbers” and in that case you can just take Int or Double as an argument.
You would have to implement them yourself, like I implemented * on the playground:
operator fun times(rhs: Number): Number = when {
rhs is Frac -> Frac(this.divisor * rhs.divisor, (this.dividend * rhs.dividend).toShort())
rhs is Long -> Frac(this.divisor * rhs, this.dividend)
else -> TODO()
}
It would give you conversion to a Number but not specific operations on fractions. When you will multiply fraction by fraction, which operations will you use?
It will work if fraction is on the left side, but if the number is on the left side? You also have a perfect chance of violating a*b = b*a condition if you start adding custom operations to anything. This is exactly why no operations are defined on numbers.