更新给定超类的子类

时间:2012-03-11 22:17:43

标签: java oop inheritance

问题描述

我有一个抽象的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 个答案:

答案 0 :(得分:3)

您可以使用每个属性的getter创建一个名为UpdateBundle的对象。

然后Paper类将有一个方法更新(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();
}

答案 1 :(得分:2)

创建方法

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

到所有论文并从Paper实现中提取相关属性。

在出版物中,它可能看起来像:

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

  this.pages = parameters.get( "pages" );
}

答案 2 :(得分:2)

我在很久以前就问了类似的问题,这个问题的答案可能对你有帮助,

Naive Inheritance Problem - Java

祝你好运!

答案 3 :(得分:0)

接受答案的问题是它要求您手动更新所有属性。如果属性列表发生更改,则必须更改update()方法,否则事情将不同步。根据我的经验,这经常发生。然后你必须花很多时间来追踪这个错误。

另一种方式(我不会称之为“更好”的方式)是使用反射或某些第三方库来复制字段。但是,有一些权衡。优点是您的代码需要的工作少得多,而且(可能)会有更少的错误。缺点是您的代码将更慢,更不灵活,并且缺乏编译时检查。

我有时使用Jackson的ObjectMapper.convertValue()来做到这一点。您可以在此处找到其他方法:Copy all values from fields in one class to another through reflection