面向对象篇之 接口&多态
0x01、接口
在前面写的几篇文章里,讲了封装和继承,那么这篇文章就来讲讲第三大面向对象的特性多态吧,在此之前先接着上篇文章的抽象先来看看Java里面接口的应用。
(1)、定义格式
public interface IA {
// 常量 默认修饰符是 public static final 这3个修饰符可以省略不写
int NUM = 10;
// 抽象方法 默认修饰符是 public abstract 这2个修饰符可以省略不写
void method1();
// 默认方法 默认修饰符是 public
default void method3(){
System.out.println("IA 接口默认方法");
}
// 静态方法 默认修饰符 public
static void method4(){
System.out.println("静态方法");
}
// 私有方法 修饰符 private private不可以省略
private void method5(){
System.out.println("私有非静态方法");
}
private static void method6(){
System.out.println("私有静态方法");
}
}
(2)、实现接口
实现概述
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements
关键字。
public interface IA{
public void show1();
}
public interface IB{
public void show2();
}
public class Zi implements IA ,IB{
public void show1(){
}
public void show2(){
}
}
-
类可以实现一个接口,也可以同时实现多个接口。
-
类实现接口后,必须重写接口中所有的抽象方法,否则该类必须是一个“抽象类”。
public interface IA{ public void show1();} public interface IB{ public void show2();} public class Zi implements IA ,IB{ public void show1(){ } public void show2(){ } }
-
类可以在“继承一个类”的同时,实现一个、多个接口;
public class Fu{}
public interface IA{}
public interface IB{}
public class Zi extends Fu implements IA,IB{//一定要先继承,后实现
}
(3)、 接口中成员的访问特点:
接口中的常量: 主要是供接口直接使用
接口中的抽象方法: 供实现类重写的
接口中的默认方法: 供实现类继承的(实现类中可以直接调用,实现类对象也可以直接调用)
接口中的静态方法: 只供接口直接调用,实现类继承不了
接口中的私有方法: 只能在接口中直接调用,实现类继承不了
(4)、多实现时的几种冲突
公有静态常量的冲突
- 实现类不继承冲突的变量
interface IA{
public static final int a = 10;
public static final int b= 20;
}
interface IB{
public static final int a = 30;
}
class Zi implements IA,IB{
//只继承了b,没有继承a,因为a冲突了
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
// System.out.println(z.a);//编译错误
System.out.println(z.b);
}
}
公有抽象方法的冲突
- 实现类只需要重写一个
公有默认方法的冲突
- 实现类必须重写一次最终版本
公有静态方法的冲突
- 静态方法是直接属于接口的,不能被继承,所以不存在冲突
私有方法的冲突
- 私有方法只能在本接口中直接使用,不存在冲突
(5)、实现类继承父类又实现接口的冲突
父类和接口的公有静态常量的冲突
- 无法继承两个重名的变量
父类和接口的抽象方法冲突
- 重写方法
父类和接口的公有默认方法的冲突
- 继承父类的默认方法,不继承接口
父类和接口的公有静态方法
- 只继承了"父类"的静态方法,没有继承接口的静态方法
父类和接口的私有方法
- 不存在冲突
0x02、多态
多态是继封装、继承之后,面向对象的第三大特性。
- 多态: 是指同一行为,对于不同的对象具有多个不同表现形式。
- 程序中多态: 是指同一方法,对于不同的对象具有不同的实现.
(1)、前提条件【重点】
-
继承或者实现【二选一】
-
父类引用指向子类对象【格式体现】
Fu fu = new Zi();
-
方法的重写【意义体现:不重写,无意义】
(2)、实现多态
多态的体现:父类的引用指向它的子类的对象:
父类类型 变量名 = new 子类对象;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
class Animal{}
class Cat extends Animal{}
class Dog extends Animal{}
clsss Person{}
//测试类:
main(){
Animal a1 = new Cat();
Animal a2 = new Dog();
Animal a3 = new Person();//编译错误,没有继承关系。
}
注意:多态的情况下是无法访问子类独有的方法
Animal父类代码:
public class Animal {
int num = 10;
public void eat(){
System.out.println("吃东西...");
}
public static void sleep(){
System.out.println("Animal类中的睡觉方法...");
}
}
Dog 继承Animal父类:
public class Dog extends Animal {
int num = 20;
// 重写
public void eat() {
System.out.println("狗吃骨头");
}
public static void sleep(){
System.out.println("Dog类中的睡觉方法...");
}
public void lookHome(){
System.out.println("狗正在看家...");
}
}
mian方法
public class Demo1 {
public static void main(String[] args) {
// 父类的引用指向子类的对象
Animal anl1 = new Dog();
// 访问非静态方法
anl1.eat();
// 访问成员变量num
System.out.println(anl1.num);//10
// 访问静态方法
anl1.sleep();
// 多态想要调用子类中独有的方法
// anl1.lookHome(); 错误的,无法访问 多态的弊端:无法访问子类独有的方法
}
}
(3) 引用类型转换
向上转型
-
子类类型向父类类型 向上转换的过程,这个过程是默认的。(只能调用父类,不能调用子类独有)
Aniaml anl = new Cat();
向下转型
-
父类类型向子类类型向下转换的过程,这个过程是强制的。
Aniaml anl = new Cat(); Cat c = (Cat)anl;//向下转型 c.catchMouse();// 可以访问 子类独有的功能,解决多态的弊端
instanceof关键字
-
向下强转有风险,最好在转换前做一个验证 :
-
格式:
变量名 instanceof 数据类型 如果变量属于该数据类型,返回true。 如果变量不属于该数据类型,返回false。 if( anl instanceof Cat){//判断anl是否能转换为Cat类型,如果可以返回:true,否则返回:false Cat c = (Cat)anl;//安全转换 }
(4)、多态的几种表现形式
-
多态的表现形式:
-
普通父类多态
public class Fu{} public class Zi extends Fu{} public class Demo{ public static void main(String[] args){ Fu f = new Zi();//左边是一个“父类” } }
-
抽象父类多态
public abstract class Fu{} public class Zi extends Fu{} public class Demo{ public static void main(String[] args){ Fu f = new Zi();//左边是一个“父类” } }
-
父接口多态
public interface A{} public class AImp implements A{} public class Demo{ public static void main(String[] args){ A a = new AImp(); //左边是一个“父类” } }
-