Java接口与多态

接口概念

接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。

接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计

接口的定义

与定义类的class不同,接口定义时需要使用interface关键字。

定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。

定义格式:

public interface 接口名 {

抽象方法1;

抽象方法2;

抽象方法3;

}

使用interface代替了原来的class,其他步骤与定义类相同:

接口中的方法均为公共访问的抽象方法

接口中无法定义普通的成员变量

类实现接口

类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements

其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。

格式:

class implements 接口 {

重写接口中方法

}

在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑

l 接口中定义功能,当需要具有该功能时,可以让类实现该接口,只声明了应该具备该方法,是功能的声明。

l 在具体实现类中重写方法,实现功能,是方法的具体实现。

于是,通过以上两个动作将功能的声明与实现便分开了。(此时请重新思考:类是现实事物的描述,接口是功能的集合。)


  类与类之间是   单继承

  类与接口是     多实现

  接口和接口是   多继承

通过上面的例子总结接口和抽象类的区别:

相同点:

都位于继承的顶端,用于被其他类实现或继承;

都不能直接实例化对象;

都包含抽象方法,其子类都必须覆写这些抽象方法;

区别:

抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;

一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)

抽象类为继承体系中的共性内容,接口为继承体系中的扩展功能


多态概述

多态是继封装、继承之后,面向对象的第三大特性。

现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。

Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person

Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。

Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。

最终多态体现为父类引用变量可以指向子类对象

多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态

在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法

父类引用指向子类对象就是多态的定义格式。同一个父类的方法会被不同的子类重写为各自的具体实现。在调用方法时,调用的为各个子类重写后的方法。

父类类型  变量名 = new 子类类型();

变量名.方法名();

此时,虽然该变量指向的是子类对象,但表现为一个父类的形态可以调用一切父类的方法,子类特有的方法将不能调用


多态的存在意义(优点)为:

配合继承与方法重写提高了代码的复用性与扩展性,如果没有方法重写,则多态同样没有意义。

    多态的弊端: 不能调用子类的特有方法


向上向下类型转换

多态本身是子类类型向父类类型向上转型的过程。

多态的转型分为向上转型与向下转型两种:

l 向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。

使用格式:

父类类型  变量名 = new 子类类型();

如:Animal  p = new Cat();

l 向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!

使用格式:

子类类型 变量名 = (子类类型) 父类类型的变量;

:Cat c = (Cat) a;  //变量p 实际上指向Cat对象


案例

请使用代码描述:    
奥迪车(Audi)都具有跑的功能,但是智能奥迪车(SmartAudi)除了具有跑的功能外,还具有自动泊车(automaticParking)和无人驾驶(automaticDrive)的功能!
要求:在测试类中创建Audi车对象和智能奥迪车对象,分别调用各自方法; 然后测试向上转型(转换为父类类型和实现的接口类型)和向下转型.


操作步骤描述
1.定义奥迪车类(Audi)
a)成员方法: 跑(run())
i.输出格式: 奥迪车在跑
2.定义智能接口(Smart)
a)抽象方法: 自动泊车(automaticParking)和无人驾驶(automaticDrive)
3.定义智能奥迪车类(SmartAudi) 继承Audi实现Smart接口
a)成员方法
i.实现automaticParking方法
1.输出:智能奥迪车在自动泊车
ii.实现automaticDrive方法
1.输出:智能奥迪车在无人驾驶
4.定义测试类Test
a)提供main方法
b)在main方法中
i.创建Audi车对象 a,调用跑方法
ii.创建SmartAudi车对象 sa,调用跑,自动泊车,自动驾驶方法
iii.定义Audi类型的变量 aa 把sa赋值aa; 测试aa只能调用run方法,不能调用其他方法
iv.判断如果aa是SmartAudi的实例对象, 把aa强制转换为saa;使用saa调用自动泊车和自动驾驶方法

v.定义Smart类型的变量 s,把sa赋值给s,测试只能调用自动泊车和自动驾驶方法,不能调用run方法.

//定义奥迪类

public class Audi {
	public void run(){
		System.out.println("奥迪车在跑");
	}
}
//定义接口Smart,两个抽象类

public interface Smart {
	public abstract void automaticParking();
	public abstract void automaticDrive();
}
//定义智能奥迪车类(SmartAudi) 继承Audi实现Smart接口

public class SmartAudi extends Audi implements Smart{

	@Override
	public void automaticParking() {
		System.out.println("智能奥迪车在自动泊车");
		
	}

	@Override
	public void automaticDrive() {
		System.out.println("智能奥迪车在无人驾驶");
		
	}

}

//定义测试类Test
public class Test {

	public static void main(String[] args) {
		Audi a = new Audi();
		a.run();
		
		SmartAudi sa = new SmartAudi();
		sa.run();
		sa.automaticDrive();
		sa.automaticParking();
		
		Audi aa = sa;
		aa.run();
		
		SmartAudi saa = (SmartAudi)aa;//向下转型
		saa.automaticDrive();
		saa.automaticParking();
		
		Smart s = sa;
		s.automaticDrive();
		s.automaticParking();

	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值