Обновление подкласса данного суперкласса - PullRequest
3 голосов
/ 12 марта 2012

Описание проблемы

У меня есть абстрактный класс Paper, который содержит общие свойства всех документов и один или несколько дочерних классов бумаги, которые добавляют дополнительную информацию для этого типа бумаги. Затем у меня есть HashMap<String, Paper> для хранения нескольких бумаг.

Мое приложение позволяет пользователю обновлять бумагу, предоставляя pid и затем предоставляя атрибуты и значения для обновления. У меня проблема в том, как обновить свойства подклассов, когда у меня есть только суперкласс.

Как лучше всего справиться с этой ситуацией?

Структура класса

public abstract class Paper {
    String pid;
    String title;
    String author;
}


public class Publication extends Paper {
    int pages;
}

public class PHDThesis extends Paper {
    String supervisor;
}

Моя текущая попытка

Это то, что у меня сейчас **, и оно работает с использованием instance of; но я чувствую, что должен быть лучший способ сделать это.

import java.util.*;

public class App {
    public static abstract class Paper {

        private String title;
        private String author;

        public Paper(String title, String author) {
            this.title = title;
            this.author = author;
        }

        public void update(String title, String author) {
            this.title = title;
            this.author = author;
        }
    }


    public static class Publication extends Paper {

        private int pages;

        public Publication(int pages, String title, String author) {
            super(title, author);
            this.pages = pages;
        }

        public void update(String title, String author, int pages) {
            super.update(title, author);
            this.pages = pages;
        }

    }

    public static class PHDThesis extends Paper {

        private String supervisor;

        public PHDThesis(String supervisor, String title, String author) {
            super(title, author);
            this.supervisor = supervisor;
        }

        public void update(String title, String author, String supervisor) {
            super.update(title, author);
            this.supervisor = supervisor;
        }
    }

    public static void main(String[] args) {
        HashMap<String, Paper> papers = new HashMap<String, Paper>();

        papers.put("P001", new PHDThesis("My Super", "My PHD Title", "My Author"));
        papers.put("P002", new Publication(22, "My Pub Title", "My Author"));

        Paper p = papers.get("P001");

        if (p instanceof PHDThesis) {
            ((PHDThesis)p).update("New Title", "New author", "New Super");
        } else if (p instanceof Publication) {
            ((Publication)p).update("New Title", "New author", 33);
        }
    }
}

** сокращен тестовый код, реальный код гораздо сложнее и лучше продуман.

Ответы [ 4 ]

3 голосов
/ 12 марта 2012

Вы можете создать объект с именем UpdateBundle с геттерами для каждого атрибута.

Тогда класс Paper будет иметь метод update (UpdateBundle), который каждый дочерний элемент будет реализовывать по-своему.

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

В отдельном примечании я не понимаю, почему класс бумаги абстрактный.Кажется, у вас нет абстрактных методов.

public abstract class Paper {
    String pid;
    String title;
    String author;

    public void update(PaperUpdateBundle bundle)
    {
        pid = bundle.getPID();
        title = budnle.getTitle();
        author = bundle.getAuthor();
    }
}


public class Publication extends Paper {
    int pages;

    public void update(PaperUpdateBundle bundle)
    {
       super.update(bundle);
       pages = bundle.getPages();
    }
}

public class PHDThesis {
    String supervisor;


    public void update(PaperUpdateBundle bundle)
    {
       super.update(bundle);
       supervisor = bundle.getSupervisor();
    }
}

public interface PaperUpdateBundle
{
    String getPID();
    String getTitle();
    String getAuthor();
    int getPages();
    String getSupervisor();
}
2 голосов
/ 12 марта 2012

Я задавал подобный вопрос давным-давно, ответы на этот вопрос могут помочь вам,

Проблема наивного наследования - Java

Удачи!

2 голосов
/ 12 марта 2012

Создайте метод

public void update( Map<String, Object> parameters );

для всех документов и извлеките из него соответствующие свойства в реализациях Paper.

В публикации он может выглядеть следующим образом:

public void update( Map<String, Object> parameters ) {
  super.update( parameters );

  this.pages = parameters.get( "pages" );
}
0 голосов
/ 06 февраля 2015

Проблема с принятым ответом состоит в том, что требуется обновить все свойства вручную.Если список свойств изменяется, вы должны изменить метод update (), иначе все будет не синхронизировано.По моему опыту это случается часто.И затем вам придется потратить много времени, пытаясь отследить ошибку.

Другой способ (я не буду называть это «лучшим» способом) - это использовать отражение или какую-либо стороннюю библиотеку.скопировать поля.Однако есть некоторые компромиссы.Преимущество в том, что ваш код требует гораздо меньше работы и (вероятно) будет иметь меньше ошибок.Недостатком является то, что ваш код будет медленнее, менее гибким и не будет проверяться во время компиляции.

Я иногда использовал для этого Джексона ObjectMapper.convertValue ().Вы можете найти другие способы сделать это здесь: Скопируйте все значения из полей одного класса в другой с помощью отражения .

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