如果要求程序员必须在某个类中特定的方法中实现一个特定的功能, 应该如何实现?
使用抽象方法或者使用接口(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;
}
@Override
public 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);//用来接收测试类传进来的实参
}
//中国移动
@Override
public void ichat() {
System.out.println("通过飞信实现了聊天");
}
@Override
public void iInternet() {
System.out.println("实现了上网");
}
@Override
public 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();
}
}
}