Java基础
媒体资料库故事
设计一个资料库,它的功能主要是存放CD。
首先设计一个CD类,一个CD的属性当然有,主题,音乐家,播放时间,评论,播放次数。
public class CD {
private String title;
private String artist;
private int playingTime;
private String comment;
private int numOfTracks;
private boolean gotIt;
public CD(String title, String artist, int playingTime, String comment, int numOfTracks) {
this.title = title;
this.artist = artist;
this.playingTime = playingTime;
this.comment = comment;
this.numOfTracks = numOfTracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public int getPlayingTime() {
return playingTime;
}
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public int getNumOfTracks() {
return numOfTracks;
}
public void setNumOfTracks(int numOfTracks) {
this.numOfTracks = numOfTracks;
}
public Boolean getGotIt() {
return gotIt;
}
public void setGotIt(Boolean gotIt) {
this.gotIt = gotIt;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "CD{" +
"title='" + title + '\'' +
", artist='" + artist + '\'' +
", playingTime='" + playingTime + '\'' +
", comment='" + comment + '\'' +
", numOfTracks=" + numOfTracks +
", gotIt=" + gotIt +
'}';
}
}
接下来设计一个资料库,通过一个容器来存储CD,这里用的List,当然这个资源库能够添加CD,而且能看到所有的CD。
public class Database {
private final List<CD> listCD = new ArrayList<>();
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();
}
}
public static void main(String[] args) {
Database database = new Database();
database.add(new CD("cd","dvd artist",60,"...",3));
database.list();
}
}
然后执行main函数测试,先添加一个CD,然后列出CD,测试结果如下。
CD{title='cd', artist='dvd artist', playingTime='60', comment='...', numOfTracks=3, gotIt=false}
这时,我们想在资源库中能够添加DVD。
首先,得添加一个DVD类。和CD区别的是这个里的DVD是一个导演,而不是音乐家。
public class DVD {
private String title;
private String director;
private int playingTime;
private String comment;
private int numOfTracks;
private boolean gotIt;
public DVD(String title, String director, int playingTime, String comment, int numOfTracks) {
this.title = title;
this.director = director;
this.playingTime = playingTime;
this.comment = comment;
this.numOfTracks = numOfTracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public int getPlayingTime() {
return playingTime;
}
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public int getNumOfTracks() {
return numOfTracks;
}
public void setNumOfTracks(int numOfTracks) {
this.numOfTracks = numOfTracks;
}
public Boolean getGotIt() {
return gotIt;
}
public void setGotIt(Boolean gotIt) {
this.gotIt = gotIt;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "DVD{" +
"title='" + title + '\'' +
", artist='" + director + '\'' +
", playingTime='" + playingTime + '\'' +
", comment='" + comment + '\'' +
", numOfTracks=" + numOfTracks +
", gotIt=" + gotIt +
'}';
}
}
资源库类调整。首先一个容器来保存DVD, 添加一个能够保存DVD的方法,然后的列出资源时,需遍历保存DVD的容器。
public class Database {
private final List<CD> listCD = new ArrayList<>();
private final List<DVD> listDVD= new ArrayList<>();
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();
}
}
public static void main(String[] args) {
Database database = new Database();
database.add(new CD("cd","dvd artist",60,"...",3));
database.add(new DVD("dvd name","dvd artist",120,"...",6));
database.list();
}
}
通过main方法测试,这里创建一个CD和一个DVD添加到资源库,然后列出,控制台结果如下。
CD{title='cd', artist='dvd artist', playingTime='60', comment='...', numOfTracks=3, gotIt=false}
DVD{title='dvd name', artist='dvd artist', playingTime='120', comment='...', numOfTracks=6, gotIt=false}
这里的程序设计是否有问题呢?请看下面。
继承
如果这时,我需要想在资源库能够添加mp3、mp4、u盘等。怎么办呢?按照上面的操作,那么又得添加一个新的容器,add方法,以及遍历容器,这些重复性操作。那么这里通过继承来解决这些问题。
首先我们添加一个Item类,然后里面添加一个print()方法。
public class Item {
public void print() {
System.out.println("this is item");
}
}
让CD和DVD类都继承Item。
CD类:
public class CD extends Item {
private String title;
private String artist;
private int playingTime;
private String comment;
private int numOfTracks;
private boolean gotIt;
public CD(String title, String artist, int playingTime, String comment, int numOfTracks) {
this.title = title;
this.artist = artist;
this.playingTime = playingTime;
this.comment = comment;
this.numOfTracks = numOfTracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public int getPlayingTime() {
return playingTime;
}
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public int getNumOfTracks() {
return numOfTracks;
}
public void setNumOfTracks(int numOfTracks) {
this.numOfTracks = numOfTracks;
}
public Boolean getGotIt() {
return gotIt;
}
public void setGotIt(Boolean gotIt) {
this.gotIt = gotIt;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "CD{" +
"title='" + title + '\'' +
", artist='" + artist + '\'' +
", playingTime='" + playingTime + '\'' +
", comment='" + comment + '\'' +
", numOfTracks=" + numOfTracks +
", gotIt=" + gotIt +
'}';
}
}
DVD类:
public class DVD extends Item {
private String title;
private String director;
private int playingTime;
private String comment;
private int numOfTracks;
private boolean gotIt;
public DVD(String title, String director, int playingTime, String comment, int numOfTracks) {
this.title = title;
this.director = director;
this.playingTime = playingTime;
this.comment = comment;
this.numOfTracks = numOfTracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public int getPlayingTime() {
return playingTime;
}
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public int getNumOfTracks() {
return numOfTracks;
}
public void setNumOfTracks(int numOfTracks) {
this.numOfTracks = numOfTracks;
}
public Boolean getGotIt() {
return gotIt;
}
public void setGotIt(Boolean gotIt) {
this.gotIt = gotIt;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "DVD{" +
"title='" + title + '\'' +
", artist='" + director + '\'' +
", playingTime='" + playingTime + '\'' +
", comment='" + comment + '\'' +
", numOfTracks=" + numOfTracks +
", gotIt=" + gotIt +
'}';
}
}
调整资源库Database类,将之前的两个容器换成一个保存Item的容器,添加时也只需要添加Item,然后遍历时也只需要遍历这一次保存Item的容器。
public class Database {
// private final List<CD> listCD = new ArrayList<>();
// private final List<DVD> listDVD = new ArrayList<>();
private final List<Item> listItem = new ArrayList<>();
// public void add(CD cd) {
// listCD.add(cd);
// }
//
// public void add(DVD dvd) {
// listDVD.add(dvd);
// }
public 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 database = new Database();
database.add(new CD("cd", "dvd artist", 60, "...", 3));
database.add(new DVD("dvd name", "dvd artist", 120, "...", 6));
database.list();
}
}
通过main方法测试,同样创建一个CD和DVD,然后列出,结果如下。调整后和上面测试的结果一摸一样。说明调整后并没有什么问题。如果想添加一个mp3,那我们只需要添加一个mp3类,然后继承这个Item即可。
CD{title='cd', artist='dvd artist', playingTime='60', comment='...', numOfTracks=3, gotIt=false}
DVD{title='dvd name', artist='dvd artist', playingTime='120', comment='...', numOfTracks=6, gotIt=false}
但是这个程序是否就完美了呢,这是只是对资源库Database类进行了优化而已,还没有对这些CD,DVD类优化,我们可以可以看到CD和DVD有很多共同的属性,所以可以把共同的属性提取到Item类中。
Item类:
public class Item {
private String title;
private int playingTime;
private String comment;
private int numOfTracks;
private boolean gotIt;
public void print() {
System.out.println("this is item");
}
public Item(String title, int playingTime, String comment, int numOfTracks) {
this.title = title;
this.playingTime = playingTime;
this.comment = comment;
this.numOfTracks = numOfTracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPlayingTime() {
return playingTime;
}
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public int getNumOfTracks() {
return numOfTracks;
}
public void setNumOfTracks(int numOfTracks) {
this.numOfTracks = numOfTracks;
}
public boolean isGotIt() {
return gotIt;
}
public void setGotIt(boolean gotIt) {
this.gotIt = gotIt;
}
}
CD类只需要保持自己特有artist的字段。然后构造器中应用父类的构造方法,给属性赋值。
CD类:
public class CD extends Item {
private String artist;
public CD(String title, String artist, int playingTime, String comment, int numOfTracks) {
super(title,playingTime,comment,numOfTracks);
this.artist = artist;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "CD{" +
"title='" + super.getTitle() + '\'' +
", artist='" + artist + '\'' +
", playingTime='" + super.getPlayingTime() + '\'' +
", comment='" + super.getComment() + '\'' +
", numOfTracks=" + super.getNumOfTracks() +
", gotIt=" + super.isGotIt() +
'}';
}
}
DVD类同样只需要保持自己特有director的字段。然后构造器中应用父类的构造方法,给属性赋值。
DVD类:
public class DVD extends Item {
private String director;
public DVD(String title, String director, int playingTime, String comment, int numOfTracks) {
super(title, playingTime, comment, numOfTracks);
this.director = director;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public void print() {
System.out.println(toString());
}
@Override
public String toString() {
return "CD{" +
"title='" + super.getTitle() + '\'' +
", director='" + director + '\'' +
", playingTime='" + super.getPlayingTime() + '\'' +
", comment='" + super.getComment() + '\'' +
", numOfTracks=" + super.getNumOfTracks() +
", gotIt=" + super.isGotIt() +
'}';
}
}
然后继续Database类的main方法测试,结果如下。
CD{title='cd', artist='dvd artist', playingTime='60', comment='...', numOfTracks=3, gotIt=false}
CD{title='dvd name', director='dvd artist', playingTime='120', comment='...', numOfTracks=6, gotIt=false}
总结
- 通过extends关键字来定义类的继承关系(比如上面的CD类和DVD类,都继承Item类);
- 子类对象可以被当作父类对象使用(比如Database类,通过Item进行,保存,添加,查询等操作)。
- 子类可以拥有父类的一些属性及方法。
多态变量
- Java的对象变量是多态的,能保存的不仅是一种类型的对象(比如上面Database类中的listItem容器,表面上保存的是Item对象,但是我们通main方法测试的时候,向里面添加的是DVD,CD对象,说明它保存了DVD,CD两种不同的对象)。
- 多态变量可以保存声明类型的对象,或者声明类型的子类对象(比如上面main方法中的,database.add()方法,这里创建的其实是CD,需要的参数其实是Item,说明可以保存Item子类)。
- 当把类型对象赋值给父类对象,称之为向上造型。
造型(Cast)
当然,这个造型不是头发的造型,而是指用括号围围起类型放在值的前面。
比如:
Item item = new Item();
CD cd = (CD) item;
向上造型
把类型对象赋值给父类对象,比如。
CD cd = new CD();
Item item = new CD();
向下造型
把类型对象赋值给子类对象。
Item item = new Item();
CD cd = (CD) item;
多态
函数调用绑定
- 静态绑定:根据对象变量的声明类型来决定。
- 动态绑定:根据对象变量的动态类型来决定(只有当程序调用的时候,才确定是那个对象变量的函数方法)。
- 成员函数中通过this这个对象调用其他对象变量。
覆盖override
- 子类和父类存在名称参数完全相同的函数,则这一对函数构成覆盖关系;
- 通过父类变量调用存在覆盖关系的函数时,会调用当时所管理的对象所属的类的函数(比如上面的Database中的list函数item的print方法,测试时,会打印出对应CD和DVD的print内容)。
Object类
所有类都继承Object类。