Using functional programming, Extract the superclass fields providing subclass object

user2083529 :

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;
};
Andrew Tobilko :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=85535&siteId=1