Java 更新给定超类的子类 问题描述
我有一个抽象的Java 更新给定超类的子类 问题描述,java,oop,inheritance,Java,Oop,Inheritance,我有一个抽象的Paper类,它包含所有论文的公共属性和一个或多个子类,这些子类为该类型的论文添加了额外的信息。然后我有一个HashMap来存储多篇论文 我的应用程序允许用户通过提供pid,然后提供要更新的属性和值来更新纸张。我遇到的问题是,当我只有一个超类时,如何更新子类上的属性 处理这种情况的最佳方法/实践是什么? 阶级结构 我目前的尝试 这就是我目前拥有的**,它通过使用的实例工作;但我觉得应该有更好的方法来做到这一点 import java.util.*; public class A
Paper
类,它包含所有论文的公共属性和一个或多个子类,这些子类为该类型的论文添加了额外的信息。然后我有一个HashMap
来存储多篇论文
我的应用程序允许用户通过提供pid
,然后提供要更新的属性和值来更新纸张。我遇到的问题是,当我只有一个超类时,如何更新子类上的属性
处理这种情况的最佳方法/实践是什么?
阶级结构
我目前的尝试 这就是我目前拥有的**,它通过使用的
实例工作;但我觉得应该有更好的方法来做到这一点
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);
}
}
}
import java.util.*;
公共类应用程序{
公共静态抽象类论文{
私有字符串标题;
私有字符串作者;
公开论文(字符串标题、字符串作者){
this.title=标题;
this.author=作者;
}
公共无效更新(字符串标题、字符串作者){
this.title=标题;
this.author=作者;
}
}
公共静态类出版物扩展了纸张{
私人网页;
公共出版物(整版页、字符串标题、字符串作者){
超级(标题、作者);
this.pages=页面;
}
公共无效更新(字符串标题、字符串作者、整型页面){
超级更新(标题、作者);
this.pages=页面;
}
}
公共静态类PHDThesis扩展论文{
私人管弦乐监督;
公共PHDThesis(字符串主管、字符串标题、字符串作者){
超级(标题、作者);
this.supervisor=主管;
}
公共无效更新(字符串标题、字符串作者、字符串主管){
超级更新(标题、作者);
this.supervisor=主管;
}
}
公共静态void main(字符串[]args){
HashMap papers=新的HashMap();
论文。put(“P001”,新博士论文(“我的超级”、“我的博士头衔”、“我的作者”);
论文发表(“P002”,新出版物(22,“我的酒吧名称”,“我的作者”);
纸张p=纸张。获取(“P001”);
if(PHDThesis的p实例){
更新(“新标题”、“新作者”、“新超级”);
}else if(发布的p实例){
((出版物)第页)更新(“新标题”,“新作者”,33);
}
}
}
**减少了测试代码,实际代码更加复杂,布局也更好。创建一个方法
public void update( Map<String, Object> parameters );
公共作废更新(地图参数);
并在文件实现中从中提取相关属性
在出版物中,它可能看起来像:
public void update( Map<String, Object> parameters ) {
super.update( parameters );
this.pages = parameters.get( "pages" );
}
public void更新(映射参数){
super.update(参数);
this.pages=parameters.get(“页面”);
}
您可以为每个属性创建一个名为UpdateBundle的对象,其中包含getter
然后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();
}
接受答案的问题在于,它要求您手动更新所有属性。如果属性列表发生更改,则必须更改update()方法,否则事情将不同步。根据我的经验,这种情况经常发生。然后你必须花很多时间来追踪这个bug
另一种方法(我不会称之为“更好的”方法)是使用反射或某些第三方库来复制字段。不过,也有一些权衡。这样做的好处是,您的代码所需的工作量要少得多,并且(可能)会有更少的bug。缺点是您的代码速度较慢,灵活性较差,并且缺少编译时检查
我有时会使用Jackson的ObjectMapper.convertValue()来实现这一点。你可以在这里找到其他方法:。我感觉以前有人问过这个问题,但我找不到答案。如果有任何副本,请链接所有副本。:)不知道为什么会在这里投票否决,发表评论会有所帮助。无论哪种方式,主要的一点是扩展类应该负责理解它的扩展属性,而不是调用类。instanceof的反射破坏了封装。我取消了我的否决票。但是你用原子弹杀死蚊子你的答案没有错,但是它没有对参数进行编译时检查。如果我想传递一个对象(或其他不能编码为字符串的类型)作为参数,它也会中断。但是,,从OOP的角度来看稍微好一点。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();
}