Используя функциональное программирование, извлеките поля суперкласса, обеспечивающие объект подкласса - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть два класса Animal и Dog, т.е.

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

public class Dog extends Animal {
    private String color;
    //public getters and setters
}

Я использую функциональное программирование 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; 
    };

}

Проблема в том, что этоне объектно-ориентированный.Если в классе Animal есть новое поле, я должен явно указать его в обоих функциональных методах, например, extractDog и extractAnimal.

Есть ли способ установить поля суперкласса внутри класса Dog, используя метод extractDog, не делая это через конструктор, то есть что-то вроде

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

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

Вы можете написать метод *, который бы дал правильный экземпляр для дальнейшего заполнения.

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

После получения объекта, заполненного свойствами Animal, вы можете продолжить упаковывать его в соответствии с типом:

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

Обновление:

Чтобы избежать рефакторинга, вызовите новый метод, т.е. extractAnimal(JsonNode node, Supplier<T> animalSupplier) из Функционального метода extractAnimal, т.е.

private Function<JsonNode, Animal> extractAnimal = node -> extractAnimal(node, Animal::new);

* Чтобы следовать функциональной парадигме, вам не обязательноработать исключительно с функциональными типами Java.Вышеупомянутый метод выражает идею более красноречиво, чем личное поле Function.

0 голосов
/ 26 ноября 2018

Уменьшите сопоставления извлечения, чтобы извлечь только поля соответствующего типа, и объявите их как BiConsumer:

    public class EntityExtraction {

        private static final BiConsumer<JsonNode, Animal> extractAnimal = (node, animal) -> {
            animal.setName(node.get("name").asText());
            animal.setAge(node.get("age").asText());
        };

        private static final BiConsumer<JsonNode, Dog> extractDog = (node, dog) -> {
            dog.setColor(node.get("color").asText());
        };
    }

Каждый BiCosnumer получает JsonNode, из которого он извлекает значения дляопределенный Animal тип.

Теперь мы расширяем EntityExtraction заводским методом, который будет возвращать извлеченный Dog:

    public static Dog extractDog(JsonNode node) {
        Dog dog = new Dog();
        BiConsumer<JsonNode, Dog> extraction = extractDog.andThen(extractAnimal);
        extraction.accept(node, dog);
        return dog;
    }

. В качестве входных данных используется только JsonNode.Поскольку предполагается извлечь Dog, он создает экземпляр и применяет к нему все необходимые сопоставления извлечения.

Чтобы отобразить JsonNode, мы используем фабричный метод.

Dog dog = EntityExtraction.extractDog(node);

Более сложные сопоставления извлечения могут быть построены путем создания цепочки извлечения.

0 голосов
/ 26 ноября 2018

Вы можете использовать #getDeclaredFields() и перебирать их.Чтобы получить только поля суперкласса, вам нужно сначала вызвать #getSuperclass().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...