I have two classes Animal and Dog i.e
public class Animal {
private String name,age;
//public getters and setters
}
public class Dog extends Animal {
private String color;
//public getters and setters
}
I am using java 8 functional programming to extract the fields from the json node i.e
public class EntityExtraction {
private Function<JsonNode, Animal> extractAnimal = node -> {
Animal animal = new Animal();
animal.setName(node.get("name").asText()));
animal.setAge(node.get("age").asText()));
return animal;
};
private Function<JsonNode, Dog> extractDog = node -> {
Dog dog = new Dog();
dog.setName(node.get("name").asText()));
dog.setAge(node.get("age").asText()));
dog.setColor(node.get("color").asText()));
return dog;
};
}
Th problem is that it's not object oriented. If there is a new field in Animal class then i have to explicitly it in both functional methods i.e extractDog and extractAnimal.
Is there a way to set the superclass fields inside the Dog class using extractDog method without doing it via constructor i.e something like
private Function<JsonNode, Dog> extractDog = node -> {
Dog dog = new Dog();
//extract superclass fields
//dog.animal = extractAnimal.apply(node);
dog.setColor(node.get("color").asText()));
return dog;
};
You could write a method* that would give a correct instance for further filling.
private <T extends Animal> T extractAnimal(JsonNode node, Supplier<T> animalSupplier) {
T animal = animalSupplier.get();
animal.setName(node.get("name").asText());
animal.setAge(node.get("age").asText());
return animal;
}
After you get an object populated with Animal
's properties, you can continue packing it accordingly to the type:
Dog dog = extractAnimal(node, Dog::new);
dog.setColor(node.get("color").asText());
...
Cat cat = extractAnimal(node, () -> getPopulatedCat());
Update:
To avoid refactoring, call the new method i.e extractAnimal(JsonNode node, Supplier<T> animalSupplier)
from the Functional method extractAnimal
i.e
private Function<JsonNode, Animal> extractAnimal = node -> extractAnimal(node, Animal::new);
*To follow the functional paradigm, you shouldn't necessarily be operating exclusively with Java functional types. The above method expresses the idea more eloquently than the private Function
field does.