学习目标
- 接口
- 三大特征——多态
- 引用类型转换
一、接口
1.1 概述
接口,是Java语言中一种引用类型,接口中只定义了方法,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。
接口的定义,它与类的定义方式相似,和类是同等级别的。使用 interface
关键字来完成接口的定义。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
引用数据类型:数组,类,接口。
接口的使用,它不能创建对象,但是可以被实现(使用implements
关键字来完成接口的实现,类似于被继承)。一个实现接口的类(可以看做是接口的子类或者叫做实现类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
类和接口的关系叫做实现关系:某个类实现了某个接口。
类和类的关系叫做继承关系:某个类继承了某个类。
1.2 定义实现格式
接口的定义格式
public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}
接口的实现格式: 接口和类不同,实现类在实现接口的时候可以实现多个接口,即接口的多实现特性。
public class InterImpl implements 接口名称,接口名称 {
// 必须实现(重写)接口中的所有的抽象方法
// 可以直接调用接口中的默认方法,方法体不适合可重写该方法
// 静态方法的作用是可以不实现接口,使用接口名直接调用
// 私有方法是给接口本身调用使用的,目的是为了提高代码的复用性
}
实现接口注意事项
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements
关键字。
1、实现类在实现接口的时候,需要实现接口中的所有的抽象方法。
2、接口中的抽象方法有默认的关键字即:public 和 abstract。即使不书写这两个关键字依然默认,所以如果接口中没有书写,那么实现类在实现接口中方法的时候一定要书写public,因为在类中如果不书写public则为默认权限,而子类实现接口中的方法时,访问权限要大于或等于父接口。
3、接口和类不同,实现类在实现接口的时候可以实现多个接口。
如果实现类实现了两个以上接口,而两个以上接口中有相同方法名的方名时(非静态),实现类只需要在类中实现一次即可。最终会调用实现类实现方法。
含有抽象方法( JDK7之前 )
抽象方法:使用abstract
关键字修饰,可以省略,没有方法体。该方法供子类实现使用。
如果实现类实现了两个以上接口,而两个以上接口中有相同方法名的抽象方名时,实现类只需要在类中实现一次即可。最终会调用实现类实现方法。
代码如下:
// 接口1
interface InterfaceName1 {
public abstract void method1();//抽象方法
void method2(); // 此处为写public关键字,但是系统默认,建议不要省略
}
//接口2
interface InterfaceName2 {
public abstract void method1();//抽象方法 和接口1中方法重名,实现类实现一次即可
public abstract void method();
}
//接口实现类
class Impl_Name implements InterfaceName1 , InterfaceName2 {
/* 当类实现接口之后,需要实现接口中的所有的抽象方法 */
// 实现的为接口2的方法
public void method(){
System.out.println("method run....");
}
// 下列实现的为接口1 和 2同名的方法以及接口2中的方法
public void method1(){
System.out.println("method1 run....");
}
// 如果接口中的方法没有写public,实现类实现方法的时候一定要记得写,否则权限报错
public void method2(){
System.out.println("method2 run....");
}
}
// 测试类
public class Demo{
public static void main(String[] args ){
// 创建实现类对象
Demo d = new Demo();
// 调用实现的方法
d.method();
d.method1();
d.method2();
}
}
含有默认方法的接口(JDK8)
在JDK8中增加了默认的方法和静态的方法,
默认方法:
使用 default
修饰,不可省略,供子类对象调用或者子类重写。默认权限修饰符是public。default关键字不可以在类中使用,只能在接口中使用。类中不写任何权限修饰符就会默认为默认权限。
默认方法的使用事项:
1、默认方法是有方法体的方法,类实现了接口之后可以直接调用。如果方法体不满足类中需求,可以在类中重写该默认方法。
2、如果类实现了两个接口中有同名的默认方法,那么实现类中没有方法指名调用具体哪一个接口中的方法。因此在这种情况下,要求实现类必须将接口同同名的默认方法重写一次。
// 接口1
interface InterfaceName1 {
public default void method(){
System.out.println("method run....");
}
public default void show(){
System.out.println("show run....");
}
}
//接口2
interface InterfaceName2 {
public default void method(){
System.out.println("method run....");
}
public default void method1(){
System.out.println("show run....");
}
}
//接口实现类
class Impl_Name implements InterfaceName1 , InterfaceName2 {
// 在实现类中必须重写两个接口中的同名的默认方法
public default void method(){
System.out.println("重写之后的...method run....");
}
// 如果其他的默认方法不适合实现类使用,可以选择重写。如果适合则不用重写
public default void method1(){
System.out.println("show方法适合使用,所以只重写method1()....");
}
}
// 测试类
public class Demo{
public static void main(String[] args ){
// 创建实现类对象
Demo d = new Demo();
// 可以直接调用接口中的默认方法
d.method();
d.method1();
d.show();
}
}
含有静态方法的接口(JDK8)
静态方法:使用 static
修饰,供接口名直接调用。不用在使用子类对象间接调用,这样调用的方式更为简单些。权限修饰符可以是public 或 private。
说明:可以使用private修饰的原因是源于静态的思想。在接口中的其他静态方法中是可以调用私有的静态方法。而使用private修饰的方法更为安全。 在JDK9的特性中一起讲。
静态方法的使用事项:
1、接口中的静态方法是可以使用接口名直接调用的,所以使用该接口的类可以不直接实现该接口直接调用静态方法。
2、如果两个接口中的静态方法重名,实现类是可以不用重写该方法的,因为调用的时候是使用接口名直接调用,使用哪个接口名则直接调用哪个接口中的静态方法。静态方法不参与重写。
3、如果接口中的方法全部都是静态方法,那么可以不用写实现类去实现,接口名调用即可。
代码如下:
// 接口1
interface InterfaceName1 {
public static void method(){
System.out.println("接口1...method run....");
}
public static void show(){
System.out.println("接口1...show run....");
}
}
//接口2
interface InterfaceName2 {
public default void method(){
System.out.println("接口2...method run....");
}
public default void show(){
System.out.println("接口2...show run....");
}
}
//接口实现类 不需要
// 测试类
public class Demo{
public static void main(String[] args ){
// 使用接口名直接调用
InterfaceName1.method();
InterfaceName1.show();
InterfaceName2.method();
InterfaceName2.show();
}
}
含有私有方法和私有静态方法(jdk9)
jdk9诞生这个新的技术主要是用来提高代码的复用性。
举例:如果本类中默认方法和静态方法有重复的内容我们需要书写很多遍。而我们把共性的内容放到私有方法中,这样减少代码的书写,并且只能在本类中使用。更加安全。
私有方法:使用 private
修饰,只供接口中的默认方法或者静态方法调用。
代码如下:
// 接口1
interface InterfaceName {
/*
在下列代码中,两个方法中都使用到了for循环相同的代码,此时如果有更多的方法中需要使用到此循环,那么这些代码又需要重复写多遍。我们可以把重复的代码写在一个私有的静态的方法中,这样就可以让其他方法(不管是静态还是非静态)去调用,从而提高代码的复用性。因为是私有的,所以安全性高。
*/
public static void method(){
System.out.println("*****************");
/*
for( int i = 1; i < 10 ; i++){
System.out.println("i=" + i);
}
*/
function();// 调用私有方法
System.out.println("*****************");
}
public default void show(){
System.out.println("==================");
/*
for( int i = 1; i < 10 ; i++){
System.out.println("i=" + i);
}
*/
function();// 调用私有方法
System.out.println("===================");
}
// 供其他方法调用的私有静态方法
private static void function(){
for( int i = 1; i < 10 ; i++){
System.out.println("i=" + i);
}
}
}
// 测试类
public class Demo{
public static void main(String[] args ){
// 使用接口名直接调用
InterfaceName1.method();
InterfaceName1.show();
}
}
优先级的问题
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。代码如下:
定义接口:
interface A {
public default void methodA(){
System.out.println("AAAAAAAAAAAA");
}
}
定义父类:
class D {
public void methodA(){
System.out.println("DDDDDDDDDDDD");
}
}
定义子类:
class C extends D implements A {
// 未重写methodA方法
}
定义测试类:
public class Test {
public static void main(String[] args) {
C c = new C();
c.methodA();
}
}
输出结果:
DDDDDDDDDDDD
1.3 接口的多继承【了解】
一个接口能继承另一个或者多个接口。接口的继承使用 extends
关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。代码如下:
定义父接口:
interface A {
public default void method(){
System.out.println("AAAAAAAAAAAAAAAAAAA");
}
}
interface B {
public default void method(){
System.out.println("BBBBBBBBBBBBBBBBBBB");
}
}
定义子接口:
interface D extends A,B{
public default void method() {
System.out.println("DDDDDDDDDDDDDD");
}
}
小贴士:
子接口重写默认方法时,必须写default关键字。
子类重写默认方法时,不用写default关键字。
1.4 其他成员特点
接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
接口中,没有构造方法,不能创建对象。
接口中,没有静态代码块。
二、 多态
2.1 概述
引入
面向对象语言三大特征:封装(private)、继承(extends)、多态。
多态:表示的是一个事物的多种表现形态。同一个事物,以不同的形态表现出来.
前提【重点】
- 继承或者实现【二选一】
- 父类或接口的引用指向子类对象【格式体现】
2.2 Java中多态的体现
多态体现的格式
父类或接口类型 变量名 = new 子类对象;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
使用父类的引用,表示自己的子类对象。或者父接口指向实现类对象.
代码如下:
Cat c = new Cat(); //使用猫类型表示自己,这里不会发生多态现象
Animal a = new Cat();//使用动物的类型再表示猫,这时就发生的多态的现象。
代码体现如下
//演示多态技术
class Animal{
public void eat(){}
public void show(){
System.out.println("show run....");
}
public void say(){
System.out.println("say run.....");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼!");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗啃骨头!!");
}
}
public class DuoTaiDemo {
public static void main(String[] args) {
//不使用多态体现
Cat c = new Cat();//子类的类型指向子类的引用
Dog d = new Dog();//子类的类型指向子类的引用
Animal a = new Animal();//父类的类型指向父类的引用
/* 多态在代码中的体现
我们在使用多态的时候,永远只能使用父类的类型接收子类的对象,而不能使用
子类的类型接受父类的对象。
*/
Animal cc = new Cat();//这里发生了多态
Animal dd = new Dog();//这里也发生了多态
Animal aa = new Animal();//这里没有发生多态
cc.eat();
dd.eat();
aa.eat();
// Demo( c );
// Demo( d );
// Demo( a );
/*c.eat();
c.say();
c.show();
d.eat();
d.say();
d.show();
代码重复使用,如果方法较多的情况下,会产生大量的重复代码
可以将所有的调用抽取到一个方法中,通过调用抽取的方法来实现
*/
}
//创建方法,传递对戏的引用,调用函数
public static void Demo( Animal a ){// Animal a = new Dog(); Animal a = new Cat();
a.eat();
a.say();
a.show();
}
/*
public static void Demo( Dog a ){//一次只能传递一种类型。使用仍然存在代码的重复
a.eat();
a.say();
a.show();
}
public static void Demo( Cat a ){//一次只能传递一种类型。使用仍然存在代码的重复
a.eat();
a.say();
a.show();
}
*/
}
多态注意事项
1、在使用多态的时候,永远只能使用父类的类型接收子类的对象,而不能使用子类的类型接收父类的对象.
2、当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。(编译看父类、运行看子类)
2.3 多态的弊端
代码演示
// 动物类
class Animal{
public void eat(){}
}
// 描述猫
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼!");
}
//猫的特有行为
public void CatchMouse(){
System.out.println("猫抓老鼠!");
}
}
//描述狗
class Dog extends Animal{
public void eat(){
System.out.println("狗啃骨头!!");
}
//狗的特有行为
public void lookHome(){
System.out.println("狗看家!!");
}
}
// 测试类
public class DuoTaiDemo {
public static void main(String[] args) {
Animal c = new Cat();
c.eat();
Animal d = new Dog();
//使用多态调用方法
d.eat();//正常
/*
如果已经发生多态现象,但是我们还想调用子类的特有属性或者行为,这时需要使用
强制类型转换,把当前父类类型转成具体的子类类型。
在多态中的类型转换问题:
1、隐式的类型提升。只要有多态就会发生类型提升(向上转型)。
2、把父类类型转成子类类型(强制类型转换,向下转型)。
什么时候使用向下转型:
只要在程序中我们需要使用子类的特有属性或行为(方法、函数)的时候,才会使用向下转型。
向下转型有风险,使用需谨慎。
在Java中要使用向下转型,必须先做类型的判断,然后在转型
Java中的类型判断 需要使用关键字 instanceof
格式:
被转的引用变量名 instanceof 被转成的类型
如果引用变量所在的那个对象 和被转成的类型一致,这个表达式返回的是true,否则是false
在多态中使用转型的时候,一定要判断,防止类型转换异常的发生:
如果在程序发生ClassCastException,一定是把不是这种类型的对象转成了这种类型。
*/
Demo(c);
}
public static void Demo( Animal a ){
/*
类型传递时自动转换成了Animal类型
在这个过程中容易将引用对象具体属于哪个子类搞混
容易出现类型转换异常的发生
*/
System.out.println("=========");
a.eat();
if( a instanceof Dog){
Dog dd = (Dog)a;
dd.lookHome();
}else{
Cat cc = (Cat)a;
cc.CatchMouse();
}
}
}
多态的弊端总结
在使用多态技术的时候,程序在编译的时候,使用多态调用成员(变量和方法),要求被调用的成员在父类中一定要存在,如果父类中没有编译就会失败。(不能使用子类特有功能或者属性)
注意:
1、只要有多态的地方,一定发生类型的提升(肯定是把子类对象使用父类类型在表示)。
2、在多态的使用中,至始至终只要子类对象,没有父类对象产生。
2.4 多态中的转型
在使用多态时,存在一个弊端:不能使用子类中特有的方法。
如果在多态中,必须要使用子类特有的功能,需要在多态操作时进行类型的转换。
复习下之前学习过的类型转换:
自动类型提升 例: double d = 12; //int类型自动提升给double类型
强制类型转换 例: double dou = 3.14; int i = (int)dou;
多态的转型分为向上转型与向下转型两种:
向上转型
- 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
使用格式:
父类类型 变量名 = new 子类类型();
如:Animal a = new Cat();
Cat类型被向上转为了Animal类型
向下转型
- 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:
子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c =(Cat) a;
如果一定要在父类引用中使用子类对象特有的功能,就需要向下转操作。
说明:子类对象中特定的功能只能子类对象自己调用。
多态类型转换的代码体现:
// 演示多态中的向下转型
class Animal{
public void eat(){}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼!");
}
//猫的特有行为
public void CatchMouse(){
System.out.println("猫抓老鼠!");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗啃骨头!!");
}
//狗的特有行为
public void lookHome(){
System.out.println("狗看家!!");
}
}
public class DuoTaiDemo {
public static void main(String[] args) {
Animal a = new Dog();
a.eat();
//向下转型
Dog dd = (Dog)a;
// 调用子类特有方法
dd.lookHome();
}
}
2.5 多态类型转换时常见异常
在多态类型转换时经常会发生一个异常错误:ClassCastException(类型转换异常)。
多态类型转换常见异常代码演示:
abstract class Animal{
abstract void eat();
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
//猫有自己的特有行为 抓老鼠
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗啃骨头");
}
//狗也有自己的行为 看家
public void lookHome(){
System.out.println("狗看家");
}
}
public class DuoTaiDemo {
public static void main(String[] args) {
Animal a= new Cat();
demo(a);//传递的是猫的对象
}
public static void demo( Animal a ){
a.eat();
//把Animal类型的a转成 Dog类的d
//Dog d = (Dog)a;//将传递过来的猫的对象强制转换为狗是不可以的,会发生转换异常
/*
向下转型有风险,使用需谨慎。
在Java中要使用向下转型,必须先做类型的判断,然后在转型
Java中的类型判断 需要使用关键字 instanceof
格式:
被转的引用变量名 instanceof 被转成的类型
如果引用变量所在的那个对象和被转的类型一致,表达式返回的是true,否则是false
在多态中使用转型的时候,一定要判断,防止类型转换异常的发生:
如果在程序发生ClassCastException,一定是把不是这种类型的对象转成了这种类型。
*/
if( a instanceof Dog ){
Dog d = (Dog)a;
d.lookHome();
}
else if( a instanceof Cat ){
Cat c = (Cat)a;
c.catchMouse();
}
}
}
总结:
多态属于欺骗行为,只要有多态,就会有类型的转换。
把子类对象赋值给父类的引用,这时发生了向上的转型(隐式类型转换)。
如果我们需要使用子类的特有行为或属性,这时必须向下转型,需要把父类的引用转成具体所指的那个对象的类型。
在向下转型的时候一定要做类型的判断,防止ClassCastException异常的发生。
向下转型判断格式
if( 父类引用变量名 instanceof 子类对象所属的类型 ){
子类类型 变量名 = (子类类型)父类引用;
}
例如:
if(a instanceof Dog) {
Dog d = (Dog)a;
}
2.6 多态中的成员特点总结
学习多态中的成员使用规律:需要掌握的是以多态形式使用成员,需要考虑程序的编译和运行2个阶段。
成员变量
成员变量:是直接使用父类引用操作变量。而没有通过其他的方法来操作。
成员变量:
在多态中,使用父类的引用访问成员变量,代码在编译的时期,需要查看父类中有没有这个成员变量,如果有,编译通过,没有编译失败。
多态中,使用父类的引用访问成员变量,编译通过的前提下,如果直接使用父类引用操作成员变量,这时操作的依然是父类中的成员变量。
简化记忆:引用变量,编译运行都看引用类中的变量(编译运行看左边)。
成员方法
在多态中,使用父类引用调用成员方法的时候,一般方法都有复写存在。
在使用父类引用调用方法的时候,编译时期要看父类中有没有这个方法,有,编译通过,没有编译失败。
在运行的时候,运行的是子类中复写父类之后的那个方法。如果没有复写,运行的肯定还是父类的方法。
··简化记忆:编译时期看左边,运行时期看右边。··
三、 接口多态综合案例
接口多态的综合案例之笔记本电脑案例的面向接口编程
耦合性概念 :耦合性就是依赖关系。
手机和电池耦合度就很高:
电脑和外接的硬件设备(鼠标,键盘)耦合度就很低。
笔记本是一个生产厂商.鼠标是另外一个生产厂商.*笔记本要使用外接的设备*,*笔记本上就要预留一些插口*,*而这些插口的预留大小和规则*,*一定要遵守某个规定*,*这时生产的笔记本才可以使用外接设备*.*而外接设备在生产的时候也应该遵守一定的规则*,*然后生产符合规则的设备*.*这样笔记本和外接设备之间就可以进行通信*.
接口的思想 :
举例:*笔记本电脑*,USB 接口的故事.
1、接口的出现对功能实现了扩展. (扩展功能)
2、接口的出现定义规则. 一方使用规则,另一方则实现规则.这样双方就可以实现通信.
3、接口的出现降低了耦合性 (解耦) 笔记本和鼠标…
阶段一需求: *笔记本电脑案例*,*按照面向对象的思想*,*用代码体现*.
类: 笔记本电脑. 属性: CPU,内存,硬盘… 行为: 运行
/*
* 描述电脑类
*/
public class Computer {
//属性
//行为
public void run(){
System.out.println("computer run....");
}
}
测试类:
/*
* 面向对象思想运行笔记本电脑中的方法
*/
public class ComputerTest {
public static void main(String[] args) {
// 创建笔记本电脑类的对象
Computer c = new Computer();
c.run();
}
}
阶段二需求 :*想要在笔记本电脑上加一个鼠标*.
类: 鼠标 行为: 开启, 关闭.
/*
* 定义一个鼠标类
*/
public class Mouse {
//行为:开启
public void open(){
System.out.println("mouse open....");
}
//行为:关闭
public void close(){
System.out.println("mouse close....");
}
}
请问:笔记本如何使用鼠标呢?
在笔记本中多了一个使用鼠标的功能,*需要修改原来笔记本类中的代码*,*添加一个功能*。
/*
* 描述电脑类
*/
public class Computer {
//属性
//行为
public void run(){
System.out.println("computer run....");
}
//拆开电脑,增加使用鼠标的功能
public void useMouse(Mouse m){
if(m != null){
m.open();
m.close();
}
}
}
测试类:
/*
* 需求一:面向对象思想运行笔记本电脑中的方法
* 需求二:在笔记本电脑上添加一个鼠标
*/
public class ComputerTest {
public static void main(String[] args) {
// 创建笔记本电脑类的对象
Computer c = new Computer();
c.run();
Mouse m = new Mouse();
//电脑使用鼠标
c.useMouse(m);
}
}
问题:如果想要加入一个键盘呢?
需要定义一个键盘类,并在电脑类中加入一个使用键盘的功能。
/*
* 定义一个键盘类
*/
public class Keyboard {
// 行为:开启
public void open() {
System.out.println("keyboard open....");
}
// 行为:关闭
public void close() {
System.out.println("keyboard close....");
}
}
电脑类:
/*
* 描述电脑类
*/
public class Computer {
//属性
//行为
public void run(){
System.out.println("computer run....");
}
//拆开电脑,增加使用鼠标的功能
public void useMouse(Mouse m){
if(m != null){
m.open();
m.close();
}
}
//拆开电脑,增加使用键盘的功能
public void useKeyboard(Keyboard k){
if(k != null){
k.open();
k.close();
}
}
}
测试类
/*
* 需求一:面向对象思想运行笔记本电脑中的方法
* 需求二:在笔记本电脑上添加一个鼠标
* 需求三:在笔记本电脑上添加一个键盘
*/
public class ComputerTest {
public static void main(String[] args) {
// 创建笔记本电脑类的对象
Computer c = new Computer();
c.run();
Mouse m = new Mouse();
//电脑使用鼠标
c.useMouse(m);
Keyboard k = new Keyboard();
//电脑使用键盘
c.useKeyboard(k);
}
}
注意:
其实发现从鼠标开始,这个问题就已经产生了.一旦需要添加新设备的时候,都需要修改电脑类的源代码,(在生活中可以理解为将电脑拆开,将外围设备添加到电脑内部). 这样扩展性就非常差。
问题 :如何在设计上进行修改和改进呢?
之前的设计在于外围设备的增加和笔记本电脑之间的耦合性过高.互相依赖太紧密.
问题 :如何降低外围设备和笔记本电脑之间的耦合性呢?
外围设备还不确定,我们不要面对外围的具体设备.为了让笔记本可以使用这些外围设备,可以事先定义好一些规则.笔记本只要使用这些规则就可以了.有了这些规则就可以对笔记本进行功能的扩展,后期这些外围设备只要符合这些规则就可以被笔记本使用了.
问题 :规则在 Java**中如何体现呢**?
接口.
实现 :
1、定义一个 USB 接口.
2、描述笔记本电脑. 行为: 运行功能, 使用USB接口的功能.
USB接口:
/*
* 定义一个USB接口
*/
public interface USB {
public void open();
public void close();
}
鼠标类:
/*
* 定义一个鼠标类
*/
public class Mouse implements USB{
//行为:开启
public void open(){
System.out.println("mouse open....");
}
//行为:关闭
public void close(){
System.out.println("mouse close....");
}
}
键盘类:
/*
* 定义一个键盘类
*/
public class Keyboard implements USB{
// 行为:开启
public void open() {
System.out.println("keyboard open....");
}
// 行为:关闭
public void close() {
System.out.println("keyboard close....");
}
}
电脑类:
/*
* 描述电脑类
*/
public class Computer {
//属性
//行为
public void run(){
System.out.println("computer run....");
}
//给电脑外围设备提供预留的功能,该功能要遵守USB接口的规则
public void useUSB( USB u ){//USB u=m
if(u != null){
u.open();
u.close();
}
}
}
测试类:
public class ComputerTest {
public static void main(String[] args) {
// 创建笔记本电脑类的对象
Computer c = new Computer();
c.run();
Mouse m = new Mouse();
//电脑使用鼠标
c.useUSB(m);
Keyboard k = new Keyboard();
// //电脑使用键盘
c.useUSB(k);
}
}
总结:发现接口的出现:
1、 扩展了笔记本电脑的功能.
2、 定义了规则.
3、降低了笔记本电脑和外围设备之间的耦合性. 解耦