设计一个媒体资料库,能存入不同类别的媒体资料,例如CD与DVD,并且能完成添加与列表等操作,需要些什么?
最基础的想法
一个代表整体库的DataBase类,内部的属性包括CD和DVD的Arraylist,对应操作通过定义自己的方法来实现,部分代码如下:
public class Database {
private ArrayList<CD> listCD = new ArrayList<CD>();
private ArrayList<DVD> listDVD = new ArrayList<DVD>();
public void add(CD cd) {
listCD.add(cd);
}
public void add(DVD dvd) {
listDVD.add(dvd);
}
public void list() {
for (CD cd : listCD) {
cd.print();
}
for (DVD dvd : listDVD) {
dvd.print();
}
}
}
因为需要CD和DVD的Arraylist,于是创造CD类和DVD类,并设置两者的内部属性和打印出内容的方法,以DVD的代码为例:
public class DVD {
private String title;
private String director;
private int playingTime;
private boolean gotIt;
private String comment;
public DVD(String title, String director, int playingTime, String comment) {
this.title = title;
this.director = director;
this.playingTime = playingTime;
this.comment = comment;
}
public void print() {
System.out.println("DVD:" + ":" + director);
}
}
第一次优化:继承的使用
不难想到,CD类与DVD类的构建是完全类似的,除了个别特有的数据,两个类之间的高度相似导致了代码复制现象,代码复制是代码质量不良的体现,不仅从观感上显得臃肿且赘余,更导致代码的可拓展性不佳:假设需要向媒体库中添加新的类型,难免导致大量的代码增改。
因此,我们需要合理利用继承关系,将这些类归为同一父类的子类,其中所有复用的代码都来自对于父类的继承,这样我们不仅避免了代码复制现象,在新增类型时便无需改动其他部分的代码,只需使它继承那个父类。
于是我们在这里设计一个Item类,它具有CD类与DVD类的共同的属性与方法,代码如下:
public class Item {
private String title;
private int playingTime;
private boolean gotIt;
private String comment;
public Item() {
}
public Item(String title, int playingTime, boolean gotIt, String comment) {
//super();
this.title = title;
this.playingTime = playingTime;
this.gotIt = gotIt;
this.comment = comment;
}
public void print() {
System.out.println(title);
}
}
而CD类与DVD类修改为继承自Item,只需初始化Item类中没有的属性,并且重写Item类的print方法,使其符合自身需要,这次以CD类为例,代码如下:
public class CD extends Item {
//private String title;
private String artist;
private int numOfTracks;
// private int playingTime;
// private boolean gotIt;
// private String comment;
public CD(String title, String artist, int numOfTracks, int playingTime, String comment) {
// this.title = title;
super(title, playingTime, false, comment);
this.artist = artist;
this.numOfTracks = numOfTracks;
// this.playingTime = playingTime;
// this.comment = comment;
}
public void print() {
System.out.print("CD:");
super.print();
System.out.print(":" + artist);
}
}
super
可以发现在对CD类的修改中有一处细节,由于属性仅在父类中,且访问属性设置为private,虽然子类确实继承了该属性,但是无法之间使用,因此需要利用super()访问,其使用方法及特性与关键字this类似,super指向当前对象的父类型特征,super()是当前对象构造方法中去调用自己父类的构造方法。
添加新媒体类型
完成继承关系的构造后,可以通过添加新的媒体类型来体会两者在方便程度上的显著区别——完全不需要改动DataBase中的代码,可以先看有了Item后、且Item的子类只有CD和DVD时DateBase的代码:
public class Database {
// private ArrayList<CD> listCD = new ArrayList<CD>();
// private ArrayList<DVD> listDVD = new ArrayList<DVD>();
private ArrayList<Item> listItem = new ArrayList<Item>();
// public void add(CD cd) {
// listCD.add(cd);
// }
//
// public void add(DVD dvd) {
// listDVD.add(dvd);
// }
private void add(Item item){
listItem.add(item);
}
public void list() {
// for (CD cd : listCD) {
// cd.print();
// }
// for (DVD dvd : listDVD) {
// dvd.print();
// }
for (Item item:listItem){
item.print();
}
}
public static void main(String[] args) {
Database db = new Database();
db.add(new CD("abc", "ai", 1, 20, "..."));
db.add(new CD("c", "ai", 3, 20, "..."));
db.add(new DVD("a", "i", 1, "..."));
db.add(new DVD("X", "ai", 20, "..."));
db.list();
}
}
不难发现其中完全没有CD与DVD本身的出现,都是借助父类的特点——子类的对象可以赋值给父类的变量,实现与原本一致的效果;因此需要新增媒体类型时,只需完成对应类的构建,并在main函数中执行想要的操作就行,新增媒体类型VideoGame代码如下:
public class VideoGame extends Item {
private int numberOfPlayers;
public VideoGame(String title, int playingTime, boolean gotIt, String comment,int number) {
super(title, playingTime, gotIt, comment);
numberOfPlayers = number;
}
@Override
public void print() {
System.out.print("VideoGame:");
super.print();
}
}
@Override
对于@Override,这是一个告诉编译器的,下方所写是在覆盖父类的对应方法的标志。
值得注意的是,通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象的所属类的函数。
运行效果
符合预期:
标签:java,String,title,DVD,6.11,多态,private,CD,public From: https://blog.csdn.net/m0_68184427/article/details/139609439