如果要求程序员必须在某个类中特定的方法中实现一个特定的功能, 应该如何实现?
使用抽象方法或者使用接口(interface)
抽象方法只能单继承,不能多继承,子类必须使用里面的抽象方法
接口可以多继承,实现类必须重写里面的方法
接口的作用?
接口是一种约定的规范,体现了规范和实现分离的思想
体现低耦合思想(减少依赖关系)
接口和接口实现类定义的语法
接口的语法
public interface 接口名{
void walk();//抽象方法1,里面没有语体
//有默认的实现方法
default void A(){System.out.println("有默认实现的方法, 属于对象");}static void defaultMethod(){System.out.println("有默认实现的方法, 属于类");}
}
}
一个子类接口可以继承多个接口:
public interface IAmphibiable extends IWalkable,ISwimable{}
实现类(implements)的语法:
public class A implements IAmphibiable{//重写覆盖IAmphibiable里面的抽象方法}
注意:
//接口名命名规范:I+驼峰命名法
//接口不能创建对象,必须有子类
实现类在实现一个接口的时候, 需要注意哪些问题?
作用:实现接口里面的抽象方法,完成功能具体的实现
1.必须覆盖接口里面的抽像方法
2.可以同时实现多个接口,并且继承在前,实现在后
3.必须完全实现接口中的所有抽象方法,或者他自己也是一个抽象类,直到里面的抽象方法被子类完全实现.
4.实现类的访问修饰符的权限必须大于接口的访问权限
接口和抽象类的区别?
分析
相同点:
1、都可以定义抽象方法
2、都不能创建对象不同点:
1、接口里面全部必须是抽象方法,抽象类中可以定义普通方法。
2、接口可以多继承,抽象类只能单继承。
3、抽象类是用于约定子类应该具备的功能;接口约定的是实现类应该具备的功能;
当需要实现某个功能时,关心的侧重点不同,接口关注的是你有没有这个功能,你是谁他不关心;
抽象类需要关心功能的同时,还得关心你是不是该类的子类。
所以,接口未来用于解耦,体现了软件开发的低耦合要求。
如何理解编译类型和运行类型?
例子
Animal d2=new Dog();//只要是Animal的子类型,d2里面的方法都有,这样的功能扩展性更好//编译时类型-->Animal d2,声明对象变量的类型,编译通过了再到运行时期,否则报错//运行时类型__>new Dog,对象的真实类型d2.eat();//先找父类有不有这个方法,有的话找子类有不有这个方法覆盖重写,有的话执行子类,否则执行父类
编译类型和运行类型只在创建对象的时候进行使用,
编译类型可以是类和接口,并且是运行类型的父类或者接口,而运行类型不可以是抽象类
什么是多态? 如何体现多态?好处是什么?
多态含义:当编译类型和运行类型不一致,一个对象具有多种状态
注意:编译类型必须是运行类型的父类或者接口
如何实现示例:
Dog d = new Dog(); //创建一只狗对象,赋给子类类型变量Animal a = new Cat(); //创建一只猫对象,赋给父类类型变量
好处:
1.对已存在代码具有可替换性
2.增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作
3.向子类提供了一个共同接口
操作多态继承关系
语法:
父类 变量名 = new 子类();
变量名.方法();
public class Animal {public void shut() {System.out.println("Animal...shout...");}
}
public class Cat extends Animal{public void shut() {System.out.println("妙妙妙...");}
}
public static void main(String[] args) {// 创建Cat对象Animal animal = new Cat();animal.shut();//妙妙妙...
结论:父类引用变量指向于子类对象,调用方法时实际调用的是子类的方法。
操作实现关系
接口 变量名 = new 子类();
变量名.方法();
public interface ISwimable{void swim();
}
public class Fish implements ISwimable{void swim(){System.out.println("自由遨游");}
}
public static void main(String[] args){ISwimable fish=new Fish();fish.swim();}
//运行结果:自由遨游
结论:接口引用变量指向实现类对象,调用方法时实际调用的是实现类实现接口的方法。
多态情况下, 方法访问的流程?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UOIc8FRX-1684759193666)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230228201405261.png)]
流程:
编译时期:先去父类中寻找该方法,找到的话就到裕兴时期,否则报错
运行时期:继续去子类找有不有该方法,有的话就运行子类的方法,没有的话就执行父类的方法
多态中的类型转换(概念和数组一样)
1.自动类型转换:把子类对象赋给父类变量(多态)
语法
父类 变量=new 子类对象();
//该变量只拥有父类自己的方法
Animal a = new Dog();//Animal是DOg的父类
Object obj = new Dog(); //Object是所有类的根类
2.强制类型转换:把父类类型对象赋给子类类型变量,父类不能直接调用子类的方法时使用强转,否则编译报错
子类类型 变量=(子类变量) 父类对象;
//该变量同时具有父类和子类的方法
由于父类没有这个方法,且需要使用子类这个方法就要强转
**注意:**父类对象的真实类型必须是子类类型
instanceof关键字
作用:判断对象是否是指定的类型
语法格式:
boolean b = 对象A instanceof 类B; //判断 A对象是否是 B类的实例?如果是,返回true
综合总结
需求中的功能做接口来用:
package cn.wolfcode._10_network;public interface IFunction {//共同的上网(IInternet)和打电话(ICall)的功能void iInternet();void iCall();
}
需求中相同的行为做父类方法,字段来使用或者抽象类(abstract)来使用(少用)
public class NetworkOperator {//网络类型
private String type;public NetworkOperator() {}public NetworkOperator(String type) {this.type = type;}public String getType() {return type;}public void setType(String type) {this.type = type;}@Overridepublic String toString() {return "网络类型是:" + type ;}//安装宽带(installBroadband)和安装有线电视(installCableTV)的行为.public void installBroadband(){System.out.println("可以安装宽带");}public void installCableTV(){System.out.println("可以安装有线电视");}
需求中自己特有的行为在子类中定义一个方法使用
需要继承父类的方法和功能,实现接口的功能
public class ChinaMobile extends NetworkOperator implements IChat,IFunction{//继承两个接口,并且必须重写父类的方法public ChinaMobile(String type){setType(type);//用来接收测试类传进来的实参}//中国移动@Overridepublic void ichat() {System.out.println("通过飞信实现了聊天");}@Overridepublic void iInternet() {System.out.println("实现了上网");}@Overridepublic void iCall() {System.out.println("实现了打电话");}}
测试类用来创建对象,做类型转换,instanceof用作对象类型的比较
package cn.wolfcode._10_network;public class Demo {public static void main(String[] args) {NetworkOperator m=new ChinaMobile("DT-LTE");dowork(m);System.out.println("=========");NetworkOperator u=new ChinaUnicom("WCDMA");dowork(u);System.out.println("=========");NetworkOperator t=new ChinaTelecom("LTE");dowork(t);}public static void dowork(NetworkOperator n){if(n instanceof ChinaUnicom){//使用instanceof进行类型的判断,instanceof用作对象类型的比较ChinaUnicom u=(ChinaUnicom) n;System.out.println("中国联通:");System.out.println(u);u.installBroadband();u.installCableTV();u.iCall();u.iInternet();}if(n instanceof ChinaTelecom){ChinaTelecom t=(ChinaTelecom) n;System.out.println("中国电信:");System.out.println(t);t.installBroadband();t.installCableTV();t.iCall();t.iInternet();}if(n instanceof ChinaMobile){ChinaMobile m=(ChinaMobile) n;System.out.println("中国移动:");System.out.println(m);m.installBroadband();m.installCableTV();m.iCall();m.iInternet();m.ichat();}}
}
();
t.iInternet();
}if(n instanceof ChinaMobile){ChinaMobile m=(ChinaMobile) n;System.out.println("中国移动:");System.out.println(m);m.installBroadband();m.installCableTV();m.iCall();m.iInternet();m.ichat();}
}
}