使用函数式编程,提取提供子类对象的超类字段

use*_*529 3 java inheritance java-8

我有两个类动物和狗即

public class Animal {
    private String name,age;
    //public getters and setters
}

public class Dog extends Animal {
    private String color;
    //public getters and setters
}
Run Code Online (Sandbox Code Playgroud)

我正在使用java 8函数式编程从json节点中提取字段,即

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; 
    };

}
Run Code Online (Sandbox Code Playgroud)

问题在于它不是面向对象的.如果Animal类中有一个新字段,那么我必须在两个功能方法中明确表示它,即extractDog和extractAnimal.

有没有办法使用extractDog方法在Dog类中设置超类字段,而无需通过构造函数来完成,例如

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;
};
Run Code Online (Sandbox Code Playgroud)

And*_*lko 6

您可以编写一个方法*,它将为进一步填充提供正确的实例.

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;
}
Run Code Online (Sandbox Code Playgroud)

获得填充了Animal属性的对象后,可以继续将其打包到类型:

Dog dog = extractAnimal(node, Dog::new);
dog.setColor(node.get("color").asText());
...
Cat cat = extractAnimal(node, () -> getPopulatedCat());
Run Code Online (Sandbox Code Playgroud)

更新:

为了避免重构,请调用new方法,即extractAnimal(JsonNode node, Supplier<T> animalSupplier)从Functional方法,extractAnimal

private Function<JsonNode, Animal> extractAnimal = node -> extractAnimal(node, Animal::new);
Run Code Online (Sandbox Code Playgroud)

*要遵循功能范例,您不一定只能使用Java功能类型.上述方法比私有Function字段更有说服力地表达了这个想法.