Java 继承和多态

Posted 箬笠蓑衣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 继承和多态相关的知识,希望对你有一定的参考价值。

一、

1、媒体资料库

package dome;
//CD类
public class CD {
	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) {
		super();
		this.title = title;
		this.artist = artist;
		this.numofTracks = numofTracks;
		this.playingTime = playingTime;
		this.comment = comment;
	}

	public  void print() //类输出
	{
	    System.out.println("CD:"+title+"-"+artist);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}
package dome;
//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, String comment, int playingTime) {
		super();
		this.title = title;
		this.director = director;
		this.playingTime = playingTime;
		this.comment = comment;
	}

	public void print() {
		System.out.println("DVD:"+title+"-"+director);
	}
}
package dome;

import java.util.ArrayList;
//媒体库
public class Datebase {
	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();
		}
	}
	
	public static void main(String[] args) {
		Datebase db=new Datebase();
		db.add(new CD("abc", "abc", 4, 60, "***"));
		db.add(new CD("def", "def", 4, 60, "***"));
		db.add(new DVD("xxx","aaa","...", 60));
		db.add(new DVD("yyy","bbb","...", 60));
        db.list();
	}

}

2、上面程序有很多重复的代码,利用父类和子类的继承,可以将公共的提取出来,作为父类,独有的作为子类,然后利用protected 或者super,实现相互调用

父类 item类程序

package dome;

public class item {
	protected String title;//将private 改为protected ,这样整个包下,所有子类都可以访问
	private int playingTime;//播放时间
	private boolean gotIt;//是否借出
	private String comment;//评论
    
	//构造器赋初始值
	public item(int playingTime, String comment) {
		super();
		this.playingTime = playingTime;
		this.comment = comment;
	}

	public void print() {
		System.out.print(playingTime+"-"+comment);//这两个private在子类输出不了,在父类定义输出
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}

由于两者作用范围不一样,所以具体的代码也不一样。

private 需要在父类中就定义构造器,并初始化。利用super传值。

protected则不用再父类中做操作,但是这种方法相对不安全。

子类

package dome;
//CD类
public class CD extends item{//继承item
	private String artist;//歌手
	private int numofTracks;//几首歌
	
	//构造函数初始化对象
	public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
		super(playingTime, comment);
		this.title = title;
		this.artist=artist;
		this.numofTracks = numofTracks;
	}

	public  void print() //类输出
	{
	    System.out.print("CD:"+title+"-"+artist+numofTracks+"-");//直接输出
	    super.print();//调用父类输出
	    System.out.println("\\n");
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}
package dome;

public class DVD extends item {//继承 item
	private String director;//导演
	
	public DVD(String title, String director, String comment, int playingTime) {
		super(playingTime,comment);
		this.title = title;
		this.director = director;
	}

	public void print() {
		System.out.print("DVD:"+title+"-"+director+"-");//只有title,director 可以输出
		super.print();//调用父类的print
		System.out.println("\\n");
	}
} 

主程序

package dome;

import java.util.ArrayList;

public class Datebase {
	private ArrayList<item> listItem=new ArrayList<item>();//用父类
    
	public void add(item i)
	{
		listItem.add(i);
	}
	
	public void list()
	{
		for(item i:listItem)
		{
			i.print();
		}
	}
	
	public static void main(String[] args) {
		Datebase db=new Datebase();
		db.add(new CD("abc", "abc", 4, 60, "***"));//本来db add的是item,这里用子类对象来赋值给父类变量,向上造型
		db.add(new CD("def", "def", 4, 60, "***"));
		db.add(new DVD("xxx","aaa","...", 60));
		db.add(new DVD("yyy","bbb","...", 60));
                db.list();
	}

}

再有注意,print()构造函数由于子类输出的独特性,所以在子类总构造了输出函数,

父类和子类中都有print输出函数,运行时会根据变量类型(item,CD,DVD )来选择适当的函数。这叫多态。

 

二、

2.1

其实就是定义了一个父类将所有共有的可以提取出来,然后子类当父类,进行运行,简化重复代码。

package Hello;

import java.util.ArrayList;
import java.util.HashSet;

public class test {
	
	public static void main(String[] args) {
		String s = "hello";
		s="hi";	 
		System.out.println(s);
		}
}

可以看到s的对象是“Hello”时,id=19;

对象是hi时,id=23;可以看出并不是Hi将hello替换掉了,而是s指向了新的对象。 

2.2

注意变量和对象的区别。变量只是声明了个名称,对象则是new了初始化个值,

父类的对象不可以赋值给子类的变量

 子类的对象可以赋给父类的变量。

 debug 程序如下

22行运行后,得到如下结果

23行运行完后

24行运行完后

it和cd指向了同一个对象。

对于基本数据类型叫类型转换,对对象来说叫造型。

三、多态

 

根据变量类型,自动调用合适的函数。

四、

 

object的函数

4.1  toString()

利用Object的toString()函数输出

修改item

package dome;

public class item {
	protected String title;//将private 改为protected ,这样整个包下,所有子类都可以访问
	private int playingTime;//播放时间
	private boolean gotIt;//是否借出
	private String comment;//评论
    
	//构造器赋初始值
	public item(int playingTime, String comment) {
		super();
		this.playingTime = playingTime;
		this.comment = comment;
	}

	public void print() {
		System.out.print(playingTime+"-"+comment);//这两个private在子类输出不了,在父类定义输出
		
	}
	
	@Override
	public String toString() {
//		return "item [title=" + title + ", playingTime=" + playingTime + ", gotIt=" + gotIt + ", comment=" + comment
//				+ ", toString()=" + super.toString() + "]";
		return playingTime+"-"+comment;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}

修改CD

package dome;
//CD类
public class CD extends item{//继承item
	private String artist;//歌手
	private int numofTracks;//几首歌
	
	//构造函数初始化对象
	public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
		super(playingTime, comment);
		this.title = title;
		this.artist=artist;
		this.numofTracks = numofTracks;
	}

	public  void print() //类输出
	{
	    System.out.print("CD:"+title+"-"+artist+"-"+numofTracks+"-");//直接输出
	    super.print();//调用父类输出
	    System.out.println("\\n");
	}
	
	@Override
	public String toString() {
		//return "CD: [artist=" + artist + ", numofTracks=" + numofTracks + ", toString()=" + super.toString() + "]";
		return "CD:"+title+"-"+artist+"-"+numofTracks+"-"+super.toString();
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        CD cd=new CD("abc","def",4,60,"good");
        cd.print();//调用 print() 函数输出
        System.out.println(cd);//调用toString()函数,不过需要自己修改输出格式
	}
}

4.2

package dome;

public class DVD extends item {//继承 item
	private String director;//导演
	
	public DVD(String title, String director, String comment, int playingTime) {
		super(playingTime,comment);
		this.title = title;
		this.director = director;
	}

	public void print() {
		System.out.print("DVD:"+title+"-"+director+"-");//只有title,director 可以输出
		super.print();//调用父类的print
		System.out.println("\\n");
	}
	
	public static void main(String[] args) {
		DVD dvd=new DVD("xxx","aaa","...", 60);
		DVD dvd1=new DVD("xxx","aaa","...", 60);
		DVD dvd2;
		dvd2=dvd;
		System.out.println(dvd.equals(dvd1));//调用了Object的equals
		System.out.println(dvd.equals(dvd2));
	}
	
}

可以看出dvd和dvd2是一样的,因为dvd2是由dvd赋值过去的,他们共同管理一个位置。

而dvd1是new初始化生成的,位置不同。

但是这里他们的内容明明是相同的,所以还需要修改代码。

4.3

package dome;

public class DVD extends item {//继承 item
	private String director;//导演
	
	public DVD(String title, String director, String comment, int playingTime) {
		super(playingTime,comment);
		this.title = title;
		this.director = director;
	}

	public void print() {
		System.out.print("DVD:"+title+"-"+director+"-");//只有title,director 可以输出
		super.print();//调用父类的print
		System.out.println("\\n");
	}
	
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		//return super.equals(obj);
		DVD dvd=(DVD)obj;//向下造型
		return director.equals(dvd.director);//导演相同
	}

	
	public static void main(String[] args) {
		DVD dvd=new DVD("xxx","aaa","...", 60);
		DVD dvd1=new DVD("xxx","aaa","...", 60);
		DVD dvd2;
		dvd2=dvd;
		System.out.println(dvd.equals(dvd1));//调用了Object的equals
		System.out.println(dvd.equals(dvd2));
	}
	
}

@Override 表明下面的函数是覆盖了父类的函数(Object的函数) ,该函数表头是固定的,不可以修改。

五、类的扩展

构造函数

创建print函数

package dome;

public class videogame extends item {
	private int numofplayer;
	private String gamename;
	
	//对象初始化
	public videogame(int numofplayer,String gamename,int playingTime, String comment) {
		super(playingTime, comment);
		// TODO Auto-generated constructor stub
		this.numofplayer=numofplayer;
		this.gamename=gamename;
	}
	
	@Override
	public void print() {
		// TODO Auto-generated method stub
		System.out.print("videogame:"+gamename+"-"+numofplayer+"-");//只有title,director 可以输出
		super.print();//调用父类的print
		System.out.println("\\n");	
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "videogame:"+gamename+"-"+numofplayer+"-"+super.toString();
	}

	public static void main(String[] args) {
		videogame vg=new videogame(5,"hah",30,"great");
		vg.print();
		System.out.println(vg);	
	}
}

 

以上是关于Java 继承和多态的主要内容,如果未能解决你的问题,请参考以下文章

Java面向对象三大特征之继承和多态

Java中的继承和多态

python小白的进阶——细说继承和多态(附代码)

Java基础知识回顾之三 ----- 封装继承和多态

Java基础知识回顾之三 ----- 封装继承和多态

廖雪峰Java2面向对象编程-3继承和多态-1继承