How to Abstract Types and inheritence in Kotlin - kotlin

I know most of you already know of the animal-cow-grass-food problem
-which states that you have a code like below, that has a type constraint on Cow (which inherits Animal ) to only eat SuitableFood (which inherits Food )
Below is the SCALA representation of the same
class Food
class Grass extends Food
class Cookies extends Food
class Fish extends Food
abstract class Animal {
type SuitableFood <: Food
def eat(food: SuitableFood)
}
class Cow extends Animal {
type SuitableFood = Grass
override def eat(food: SuitableFood) = {}
}
val bessy: Animal = new Cow
bessy eat new Fish
bessy eat new Cookies
I was wondering if similar is possible in KOTLIN or JAVA ?

Not sure what you want to achieve. Restriction for Cow to eat only Grass ?
I think this can be done through generic types.
abstract class Food
open class Grass : Food()
class GreenGrass : Grass()
class Fish : Food()
abstract class Animal<T : Food> {
fun eat(food: T) { ... }
}
class Cow : Animal<Grass>()
class Bear : Animal<Fish>()
class Test {
fun test() {
val cow = Cow()
cow.eat(Grass()) // ok
cow.eat(GreenGrass()) // ok
cow.eat(Fish()) // not ok
val bear = Bear()
bear.eat(Fish()) // ok
bear.eat(Grass()) // not ok
}
}

Related

Kotlin generic type mismatch

Is it possible to accept subclass of a class in generics? It works in Java but unfortunatelly I don't know how to make it work in Kotlin.
Simplified problem:
open class Food
class Meat : Food()
interface Animal<T : Food> {
fun eat(food : T)
}
class Dog : Animal<Meat> {
override fun eat(food: Meat) {
// Dog eats meat
}
}
lateinit var pet : Animal<Food>
fun <T : Food> setAnimal(animal: Animal<T>) {
pet = animal // DO NOT COMPILE
}
I would like to method setAnimal() accept all of the animals, no matter which food it likes, and I would like to keep reference to that animal. I thought Kotlin is 100% compatible with Java but when I try to convert class to Kotlin it doesn't convert well and I have to fix that issue. I read a lot of articles but still have no idea how to make it work.
EDIT:
Java code that solves problem but how to do that in Kotlin?
public class Test {
class Food {}
class Meat extends Food {}
interface Animal<T extends Food> {
void eat(T food);
}
class Dog implements Animal<Meat> {
#Override
public void eat(Meat food) {
}
}
private Animal animal;
public void setAnimal(Animal animal) {
this.animal = animal;
animal.eat(new Meat());
}
}
EDIT 2
Sample code which uses out Food, as it was proposed. I've marked line that do not compile.
open class Food
class Meat : Food()
interface Animal<T : Food> {
fun eat(food : T)
}
class Dog : Animal<Meat> {
override fun eat(food: Meat) {
// Dog eats meat
}
}
lateinit var pet : Animal<out Food>
fun <T : Food> setAnimal(animal: Animal<T>) {
val pet : Animal<out Food> = animal
pet.eat(Meat()) // DO NOT COMPILE
}
Use out modifier on pet variable definition
lateinit var pet : Animal<out Food>
More information https://kotlinlang.org/docs/reference/generics.html

Is there a way to override an abstract property with a subtype of the declared type?

Consider the following example: I have an abstract class for Animal, and every animal has a mouth, but because every animal's mouth is different, the mouth class is also abstract:
abstract class Animal {
var numberLegs: Int = 4
var mouth: Mouth? = null
}
abstract class Mouth {
abstract fun makeSound()
}
I can now create a Dog and a DogMouth:
class Dog: Animal() {
override var mouth: Mouth = DogMouth()
}
class DogMouth: Mouth() {
override fun makeSound() {
println("Bark!")
}
}
But this allows me to also assign other types of mouths to the dog, which I don't want, e.g.:
class CatMouth: Mouth() {
override fun makeSound() {
println("Meow!")
}
}
fun main() {
val dog = Dog()
dog.mouth.makeSound() // will print "Bark!"
dog.mouth = CatMouth() // I don't want this to work
dog.mouth.makeSound() // will print "Meow!"
}
And setting override var mouth: DogMouth = DogMouth() doesn't work.
How can I make sure that Dogs only have DogMouths (and other dog body parts)?
Similar problems are addressed here and here.
The solution is to use a generic parameter:
abstract class Animal<MouthType: Mouth> {
var numberLegs: Int = 4
abstract var mouth: MouthType
}
class Dog: Animal<DogMouth>() {
override var mouth: DogMouth = DogMouth()
}
This makes dog.mouth = CatMouth() fail with a type mismatch.
With more body parts extra generics need to be added:
abstract class Animal<MouthType: Mouth, EarType: Ear, TailType: Tail> {
var numberLegs: Int = 4
abstract var mouth: MouthType
abstract var ear: EarType
abstract var tail: TailType
}

How do I implement polymorphism in Scala

I've been learning Scala for web-development for quite some time, and I have stumbled upon a lack of interfaces. Coming from PHP, I used interfaces quite a lot for method-level polymorphism and IoC like this:
interface iAnimal
{
function makeVoice();
}
class Cat implements iAnimal
{
function makeVoice()
{
return "Meow";
}
}
class Dog implements iAnimal
{
function makeVoice()
{
return "Woof!";
}
}
class Box
{
private $_animal;
function __construct(iAnimal $animal)
{
$this->_animal = $animal;
}
function makeSound()
{
echo $this->_animal->makeVoice();
}
}
And so on, and that was an easy way to ensure that anything I passed to the Box object had a makeVoice method that I was calling elsewhere. Now, what I'm curious of, is how do I implement similar functionality with Scala. I tried searching for this, but info is quite scarce. The only answer I found was to use traits, but as far as I know, they are used for concrete implementation, not declaration.
Thanks in advance.
As per other answers, the solution is to use traits :
trait Animal {
def makeVoice(): Unit //no definition, this is abstract!
}
class Cat extends Animal{
def makeVoice(): Unit = "Meow"
}
class Dog extends Animal{
def makeVoice(): Unit = "Woof"
}
class Box(animal:Animal) {
def makeSound() = animal.makeVoice()
}
A trait in Scala will be directly compiled to an interface in Java. If it contains any concrete members then these will be directly copied into any class that inherits from the trait. You can happily use a Scala trait as an interface from Java, but then you don't get the concrete functionality mixed in for you.
However... this is only part of the picture. What we've implemented so far is subtype polymorphism, Scala also allows for ad-hoc polymorphism (a.k.a typeclasses):
// Note: no common supertype needed here
class Cat { ... }
class Dog { ... }
sealed trait MakesVoice[T] {
def makeVoice(): Unit
}
object MakesVoice {
implicit object CatMakesVoice extends MakesVoice[Cat] {
def makeVoice(): Unit = "Meow"
}
implicit object DogMakesVoice extends MakesVoice[Dog] {
def makeVoice(): Unit = "Woof"
}
//helper method, not required, but nice to have
def makesVoice[T](implicit mv: MakesVoice[T]) = mv
}
import MakesVoice._
//context-bound version
class Box[T : MakesVoice] {
//using a helper:
def makeSound() = makesVoice[T].makeVoice()
//direct:
def makeSound() = implicitly(MakesVoice[T]).makeVoice()
}
//using an implicit param
class Box[T](implicit mv : MakesVoice[T]) {
def makeSound() = mv.makeVoice()
}
What's important here is that the MakesVoice type class can be associated with any type regardless of what hierarchies it belongs to. You can even use type classes with primitives or types imported from a 3rd party library that you couldn't possibly retrofit with new interfaces.
Of course, you have parametric polymorphism as well, which you'd probably know better as "generics" :)
Traits are used for both declaration and concrete implementation. Here is a direct translation of your example
trait Animal {
def makeVoice()
}
class Cat extends Animal{
override def makeVoice(): Unit = "Meow"
}
class Dog extends Animal{
override def makeVoice(): Unit = "Woof"
}
class Box(animal:Animal) {
def makeSound()={
animal.makeVoice()
}
}
Additionally, you are able to actually define a concrete implementation directly in the trait which is useful for behaviours shared by members of different class hierarchies:
trait Fish{
def swim()="Swim"
}
class Truit extends Fish
trait Bird{
def fly() = "Fly"
}
class Eagle extends Bird
class Duck extends ???{
def swim=???
def fly=???
}
The duck both swims ans flies, you could define it as such :
trait Swimmer{
def swim
}
trait Fish extends Swimmer{
def swim()="Swim"
}
class Truit extends Fish
trait Bird{
def fly()="Fly"
}
class Eagle extends Bird
class Duck extends Bird with Swimmer

Jackson Polymorphism

I have a class Animal and subclass Cat and Dog that extends Animal.
I have a class called Zoo having a variable as List;
i.e.
Class Animal {
String name;
}
Class Cat Extends Animal {
String color;
}
Class Zoo {
List<Animal> animalsInZoo;
public void printAnimalClass()
{
for(Animal a :animalsInZoo)
{
System.out.println(a.getClass.getName());
}
}
}
The object of zoo will have animals that can be objects of Animal or subclass of Animal
Following is sample JSON representation of Object of Zoo class.
{ "animalsInZoo" :
[
{"name":"A"},
{"name": "B","color":"white"}
]
}
I have to convert this into java object in such a way that first animal in list get converted into Object of class Animal and second gets converted into object of Class Cat
You have to do the conversion yourself, supposing you have another animal with same property:
Class Horse Extends Animal {
String color;
}
jackson doesn't know convert {"name": "B","color":"white"} into Cat or Horse.
you may add a property to mark which animal you need to convert to.

Hiding Jackson type info on certain (fields) situations?

The example
Java:
#JsonTypeInfo(
use = JsonTypeInfo.Id.MINIMAL_CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "#type")
public class Pet{
String name;
}
public class Dog extends Pet{}
public class Cat extends Pet{}
public class PetHouse {
List<Pet> pets;
}
public class BarkingData {
int decibels;
Dog dog;
}
JSON Serialization
petHouse = {
pets :
[
{'#type': 'Dog', 'name':'Droopy'},
{'#type': 'Cat', 'name':'Scratchy'},
{'#type': 'Dog', 'name':'Snoopy'}
]
}
barkingData = {
decibels:15,
dog:{'#type':'Dog', 'name':'Droopy'}
}
The Question
Class BarkingData has a field of type Dog (cats don't bark do they). Is it possible to tell Jackson not to include typeInfo for instances where that type can be "hinted" from the declaring field ?
So that the output of Barking data looks like :
barkingData = {
decibels:15,
dog:{'name':'Droopy'}
}
Your idea that you know the dynamic type (actual type) of this field because the static type is Dog and not Animal only works if there are no subclasses of Dog. If you make the Dog class final, then Jackson knows it can safely leave out the type info.
Additionally, you can override Jackson's type info settings, in more complex ways, for fields of static type Dog, by adding a #JsonTypeInfo annotation to the definition of the Dog class.