接口、继承与多态(笔记)

类的继承

在Java中使用extends关键字来标识两个类的继承关系。
在这里插入图片描述
例:

class Test{
	public Test(){       //构造方法
		//SomeSentence
	}
	protected void doSomething(){   //成员方法
		//SomeSentence
	}
	protected Test doIt(){   //方法返回值类型为Test类型
		return new Test();
	}
}

class Test2 extends Test{  //继承父类
	public Test2(){         //构造方法
		super();            //调用父类构造方法
		super.doSomething();  //调用父类成员方法		
	}
	public void doSomethingnew(){   //新增方法
		//SomeSentence
	}
	public void doSomething(){      //重写父类方法
		//SomeNewSentence
	}
	protected Test2 doIt(){         //重写父类方法,方法返回值类型为Test2类型
		return new Test2();
	}	
}

当重写父类方法时,修改方法的修饰权限只能从小的范围到大的范围改变。
子类重写父类的方法还可以修改方法的返回值类型,如例子中子类的doIt()方法。这种重写方式需要遵循一个原则,即重写的返回值类型必须是父类中同一方法返回值类型的子类,而Test2类正是Test类的子类。
在Java中一切都以对象的形式进行处理,在继承的机制中,创建一个子类对象,将包含一个父类子对象,这个对象与父类创建的对象是一样的。两者的区别在于后者来自外部,前者来自子类对象的内部。当实例化子类对象时,父类对象也相应被实例化,换句话说,在实例化子类对象时,Java编译器会在子类的构造方法中自动调用父类的无参构造方法。
例:

class Test1{
	Test1(){       
		System.out.println("调用父类的Test1()构造方法");
	}
}

class Test2 extends Test1{     //继承Test1类
	Test2(){      
		System.out.println("调用子类的Test2()构造方法");		
	}	
}


public class Test3 extends Test2{     //继承Test2类
	Test3(){        
		System.out.println("调用子类的Test3()构造方法");		
	}
	public static void main(String[] args){
		Test3 t = new Test3();       //实例化子类对象
	}
}
调用父类的Test1()构造方法
调用子类的Test2()构造方法
调用子类的Test3()构造方法

从本例的运行结果可以看出,在子类Test3的主方法中之调用子类的构造方法实例化子类对象,并且在子类构造方法中没有调用父类构造方法的任何语句,到那时在实例化子类对象时它相应调用了父类的构造方法。
在实例化子类对象时,父类无参构造方法将被自动调用,但有参构造方法并不能被自动调用,只能依赖与super关键字显式地调用父类的构造方法。
如 果 使 用 f i n a l i z e ( ) 方 法 对 对 象 进 行 清 理 , 需 要 确 保 子 类 的 f i n a l i z e ( ) 方 法 的 最 后 一 个 动 作 是 调 用 父 类 的 f i n a l i z e ( ) 方 法 , 以 保 证 当 垃 圾 回 收 对 象 占 用 内 存 时 , 对 象 的 所 有 部 分 都 能 被 正 常 终 止 。 \color{maroon}{如果使用finalize()方法对对象进行清理,需要确保子类的finalize()方法的最后一个动作是调用父类的finalize()方法,以保证当垃圾回收对象占用内存时,对象的所有部分都能被正常终止。} 使finalize()finalize()finalize()

Object类

在Java中,所有的类都直接或间接继承了java.lang.Object类。Object类是所有类的父类,是Java类层中的最高层类。在Object类中主要包括clone(), finalize(), equals(), toString()等方法,其中常用的两个方法为equals()和toString()方法。由于所有的类都是Object类的子类,所以任何类都可以重写Object类中的方法。
O b j e c t 类 中 的 g e t C l a s s ( ) , n o t i f y ( ) , n o t i f y A l l , w a i t ( ) 等 方 法 不 能 被 重 写 , 因 为 这 些 方 法 被 定 义 为 f i n a l 类 型 。 \color{red}{Object类中的getClass(), notify(), notifyAll, wait()等方法不能被重写,因为这些方法被定义为final类型。} ObjectgetClass(),notify(),notifyAll,wait()final

1. getClass()方法

它会返回对象执行时的Class实例,然后使用此实力调用getName()方法可以取得类的名称。
getClass().getName();
可以将getClass()方法与toString()方法联合使用。

2. toString()方法

功能是将一个对象返回为字符串形式,它会返回一个String实例。在实际的应用中通常重写toString()方法,为对象提供一个特定的输出模式。

3. equals()方法

equals()方法比较的是两个对象的实际内容。

对象类型的转换

1. 向上转型
class Quadrangle{                       //四边形类
	public static void draw(Quadrangle q){       
		//somesentence
	}
}

public class Parallelogram extends Quadrangle{     //平行四边形类,继承了四边形类
	public static void main(String args[]){      
		Parallelogram p = new Parallelogram();
		draw(p);  								//调用父类方法
	}	

在这里插入图片描述
由于向上转型是从一个较具体的类到较抽象的类的转换,所以它总是安全的,如可以说鹏兴四边形是特殊的四边形,但不能说四边形是平行四边形。

2. 向下转型

向下转型是将较抽象类转换为较具体的类。这样的转型通常会出现问题。
Quadrangle q = new Parallelogram();
Parallelogram p = (Parallelogram) q; //将四边形对象看作是平行四边形对象,称为向下转型
越是具体的对象具有的特性越多,越抽象的对象具有的特性越少,在做向下转型操作时,将特性范围小的对象转换为特性范围大的对象肯定会出现问题,所以这时需要告知编译器这个四边形就是平行四边形。

3. 使用instanceof操作符判断对象类型

当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生ClassCastException异常,所以在执行向下转型之前需要养成好习惯,判断父类对象是否为子类对象的实例。这个判断通常使用instanceof操作符来完成。可以使用instanceof操作符判断是否一个类实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。
instanceof的语法格式:
myobject instanceof ExampleClass
返回值为布尔值,如果返回值为true,说明myobject对象为ExampleClass的实例对象;如果返回值为false,说明myobject对象不是ExampleClass的实例对象。
例:

class Quadrangle{                       //四边形类
	public static void draw(Quadrangle q){       
		//somesentence
	}
}

class Square extends Quadrangle{
	//somesentence
}

class Anything{
	//somesentence
}

public class Parallelogram extends Quadrangle{
	public static void main(String args[]){ 
		Quadrangle q = new Quadrangle();		//实例化父类对象
		//判断父类对象是否为Parallelogram子类的一个实例
		if(q instanceof Parallelogram){
			Parallelogram p = (Parallelogram) q;	//向下转型操作
		}
		//判断父类对象是否为Square子类的一个实例
		if(q instanceof Square){
			Square s = (Square) q;	//进行向下转型操作
		}
		
		//System.out.println(q instanceof Anything);
	}	
}
5. 方法的重载

方法的重载就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。
在这里插入图片描述

6. 多态

利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。
例:
创建Quagrangle类,再分别创建两个内部类Square和Parallelogramle,他们都继承了Quagrangle类。编写draw()方法,该方法接收Quadrangle类的对象作为参数,即使用这两个内部类的父类作为方法参数。在主方法中分别以两个内部类的实例对象作为参数执行draw()方法

public class Quadrangle{
	//实例化保存四边形对象的数组对象
	private Quadrangle[] qtest = new Quadrangle[6];
	private int nextIndex = 0;
	public void draw(Quadrangle q){       //定义draw()方法,参数为四边形对象
		if (nextIndex < qtest.length){
			qtest[nextIndex] = q;
			System.out.println(nextIndex);
			nextIndex++;
		}
	}
	
	public static void main(String[] args){
		//实例化两个四边形对象,用于调用draw()方法
		Quadrangle q = new Quadrangle();
		q.draw(new Square());			//以正方形对象为参数调用draw()方法
		q.draw(new Parallelogramgle());	//以平行四边形对象为参数调用draw()方法
	}
}
//定义一个正方形类,继承四边形类
class Square extends Quadrangle{
	public Square(){
		System.out.println("正方形");
	}
}
//定义一个平行四边形类,继承四边形类
class Parallelogramgle extends Quadrangle{
	public Parallelogramgle(){
		System.out.println("平行四边形");
	}
}
正方形
0
平行四边形
1
7.抽象类与接口

通常可以说四边形具有4条边,或者更具体一点,平行四边形是具有对边平行且相等特性的特殊四边形,等腰三角形是其中两条边相等的三角形,这些表述都是合乎情理的,但对于图形对象却不能使用具体的语言进行描述,它有几条边,究竟是什么图形,没人能说清楚,这种类在Java中被定义为抽象类。

7.1 抽象类

在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。在Java语言中设置抽象类不可以实例化对象,因为图形类不能抽象出任何一种具体的图形,但它的子类却可以。
抽象类的语法如下:

public abstract class Test{
		abstract void testAbstract(); //定义抽象方法
}

其中,abstract是定义抽象类的关键字。
在这里插入图片描述

7.2 接口

接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。对于7.1中一流的问题,可以将draw()方法封装到一个接口中,使需要draw()方法的类实现这个接口,同时也继承图形类,这就是接口存在的必要性。
在这里插入图片描述
接口使用interface关键字进行定义,其语法如下:

public Interface drawTest{
		void draw(); //接口内的方法,省略abstract关键字
}

一个类实现一个接口可以使用implements关键字,代码如下:

public class Parallelogram extends Quadrangle implements drawTest{
		...//
}

在接口中定义的任何字段都自动是static和final的。
修改上例,将多态技术与接口相结合:
例:在项目中创建 QuadrangleUseInterface类,在类中创建两个继承该类的内部类ParallelogramgleUseInterface和SquareUseInterface;再创建drawTest接口,并使前两个内部类实现该接口;然后再主方法中分别调用这两个内部类的draw()方法。

package notebook;

interface drawTest{				//定义接口
	public void draw();			//定义方法
}
//定义平行四边形类,该类继承了四边形类,并实现了drawTest接口
class ParallelogramgleUseInterface extends QuadrangleUseInterface implements drawTest{
	public void draw(){		//由于该类实现了接口,所以要覆盖draw()方法
		System.out.println("平行四边形.draw()");
	}
	void doAnyThing(){		//覆盖父类方法
		//SomeSentence
	}
}

class SquareUseInterface extends QuadrangleUseInterface implements drawTest{
	public void draw(){		//由于该类实现了接口,所以要覆盖draw()方法
		System.out.println("正方形.draw()");
	}
	void doAnyThing(){		//覆盖父类方法
		//SomeSentence
	}
}

class AnyThingUseInterface extends QuadrangleUseInterface{
	void doAnyThing(){		//覆盖父类方法
		//SomeSentence
	}
}
package notebook;

public class QuadrangleUseInterface{	//定义四边形类
	public void doAnyTthing(){
		//SomeSentence
	}
	
	public static void main(String[] args){
		drawTest[] d = {		//接口也可以进行向上转型操作
			new SquareUseInterface(), new ParallelogramgleUseInterface()
		};
		for (int i=0; i<d.length; i++){
			d[i].draw();	//调用draw()方法
		}
	}	
}
正方形.draw()
平行四边形.draw()

在Java中不允许多重继承,但使用接口就可以实现多重继承,因为一个类可以同时实现多个接口,这样可以将所有需要继承的接口放置在implements关键字后并使用逗号隔开,但这可能会在一个类中产生庞大的代码量,因为继承一个接口时需要实现接口中所有的方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值