I am studying classes extends in kotlin and I came across this error. Can you please explain to me why this is so:
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // Error: Type mismatch
}
CodePudding user response:
Kotlin’s type inference is one of the most popular Kotlin features in the JVM world. So popular that Java 10 introduced type inference as well (limited comparing to Kotlin). Though, there are some dangers in using this feature. Above all, we need to remember that the inferred type of an assignment is the exact type of the right side, and not a superclass or interface:
In most cases, this is not a problem. When we have too restrictive type inferred, we just need to specify it and our problem is solved:
open class Animal
class Zebra: Animal()
fun main() {
var animal: Animal = Zebra()
animal = Animal()
}
Though, there is no such comfort when we don’t control a library or another module. In such cases, inferred type exposition can be really dangerous. Let’s see an example. Let’s say that you have the following interface used to represent car factories
interface CarFactory {
fun produce(): Car
}
There is also a default car used if nothing else was specified:
val DEFAULT_CAR: Car = Fiat126P()
Now, all your factories can only produce Fiat126P . Not good. If you defined this interface yourself, this problem will be probably caught soon and easily fixed. Though, if it is a part of the external API ( Elements (classes, functions, objects) that might be used from some outer module or some part of our code maintained by different developers. For instance, in libraries, those are all public and protected classes, func- tions and object declarations), you might be informed first by angry users. Except that, the return type is important information when some- one does not know API well, and so for the sake of readability, we should make it explicit especially in parts of our API visible from outside (so exposed API).
CodePudding user response:
The var animal = Zebra()
is just a syntactic sugar for
var animal:Zebra = Zebra()
this should be clear.
Then the question why we cannot assign super class? Because methods are being called on objects not references. If in the future the Zebra
class will have method fun roar()
the compiler would not be able to ensure that the animal
variable will be able to execute such if it would allow to assign there something else that declared type or subclass of this type
Read more:
CodePudding user response:
Kotlin (actually the IDE) infers the type of animal to Zebra:
var animal = Zebra() // animal is of type Zebra
animal = Animal() // type mismatch since Animal is not a Zebra
If you specify the type explicitly to be Animal, then you can assign an Animal on the next line:
var animal: Animal = Zebra() // animal is of type Animal
animal = Animal() // this works