07.多态,接口
Posted yinjian528
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07.多态,接口相关的知识,希望对你有一定的参考价值。
接口 方法实现implements
首先接口是一种区别于继承的JAVA语法,可以理解成为,遵从于既定规范的都可以去使用,使得适配性更好。
接口是引用数据类型。是内部封装了方法。
重点:
解释接口作用和继承关系
抽象类:是为了抽象方法存在,重写方法,类似于告诉你怎么去重写,因为抽象方法是父类定义的,自己重写就行
接口:是为了用类实现,你随便实现,按照我的规定就行.
接口>抽象类>普通类
领导 >小组长>员工
领导定下大家共享的不许改规矩和参数,小组长写个Demo 员工继承继续实现.
public static final 领导肯定不干活,所以不能new对象,小组长写Demo继承领导,增加点细节参数,也不干活,也不能new,剩下员工搞定去继承实现.
定义:
接口和类的定义相似,使用interface关键字,同时也会被编译成为.class文件,
引用数据类型:数组,类,接口
使用:
接口不可以直接创造对象,但是可以被implements关键字实现,类似于extends,一个接口实现类必须实现接口的所有抽象方法,如不全实现必须是抽象类。
接口内部:
- JAVA7版本支持,常量,抽象方法,规矩和定额
- JAVA8版本支持,静态方法,默认方法,领导发慈悲给的方法和工具
- JVAV9版本支持,私有方法,
接口的定义格式:
1
1
1
public interface 接口名称{}
接口内部的定义格式:
1
//抽象方法,抽象方法用abstract关键字修饰,没有方法体,该方法供子类实现
2
public abstract void method(){};
3
//默认方法,针对于子类的调用和重写,可以解决接口升级问题,接口添加新的抽象方法,每个实现类必须重新实现,牵一发动全身,使用默认方法解决公共新方法的实现,实现类可以继承接口的默认方法,默认方法要有方法体
4
public default void mehthod(){方法体};
5
//静态方法,静态方法是不于对象发生关系的,只和类发生关系。静态方法也要有方法体。
6
public static void method(){方法体};
7
//私有方法;私有方法和私有静态方法,使用private修饰供接口中的方法和静态方法调用 不是私有默认方法,私有方法是为了不让实现类得到然后给接口内部调用的。
8
private void method(){方法体};
9
private static void method(){方法体};
10
//常量;定义了不可变的成员变量,相当于常量;必须直接赋值,常量大写。
11
public static final MUN = 10
接口的基本实现
类和接口的关系是实现关系,依靠implements关键字实现接口的抽象方法。
非抽象的类:必须重写接口中的所有抽象方法,继承了接口的默认方法,
实现格式:
4
4
1
class 类名 implements 接口名{
2
//重写接口的抽象方法
3
//重写接口的默认方法(非必须)
4
}
抽象方法的使用:
21
1
public interface LiveAble {
2
// 定义抽象方法
3
public abstract void eat();
4
public abstract void sleep();
5
}
6
//实现接口
7
public class Animal implements LiveAble {
8
@Override public void eat() { System.out.println("吃东西"); }
9
@Override public void sleep() { System.out.println("晚上睡"); }
10
}
11
//测试类
12
public class InterfaceDemo {
13
public static void main(String[] args) {
14
// 创建子类对象
15
Animal a = new Animal();
16
// 调用实现后的方法
17
a.eat();
18
a.sleep();
19
}
20
}
21
输出结果: 吃东西 晚上睡
默认方法的使用 动态绑定,同名必须重写 用子类对象调用 ,父子同名必须重写。
1
//继承默认方法,创建子类对象,直接调用
2
Animal a = new Animal();
3
a.fly();
4
//重写默认方法,创建子类对象,调用后使用重写以后的方法。谁调用使用谁的方法。
5
public class Animal implements LiveAble {
6
@Override
7
public void fly() { System.out.println("自由自在的飞"); }
8
}
静态方法的使用 只用接口调用,不能用对象,父子都不行.
静态只和类有关系,接口中的静态只和接口有关,不和对象有关,所以在调用的时候,用接口来调用。
1
public interface LiveAble { public static void run(){ System.out.println("跑起来~~~"); } }
2
public class Animal implements LiveAble { // 无法重写静态方法 }
3
public class InterfaceDemo {
4
public static void main(String[] args) {
5
// Animal.run(); // 【错误】无法继承方法,也无法调用
6
LiveAble.run(); //静态方法直接使用接口点方法调用 }
7
}
8
输出结果: 跑起来~~~
私有方法的使用
私有方法是在JAVA 9中实现的,主要解决接口中默认方法和静态方法这种自带方法体方法的重复代码问题。
在接口里,私有化的方法分成两种
私有方法:私有方法是为接口中默认方法服务的,只能是默认方法在接口中进行调用,不参与到实现类中,
私有静态方法:默认方法和静态方法可以调用,静态意味先加载,不依附于对象存在。
3
3
1
普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }
2
静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }
3
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
接口的多实现
接口区别于继承的是,继承是子类只可以继承一个父类,接口是一个类可以实现多个接口,也叫接口的多实现。并且可以一个类继承一个父类,同时实现多个接口。
继承多个接口可以有全部方法.
3
3
1
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
2
// 重写接口中抽象方法【必须】 // 重写接口中默认方法【不重名时可选】
3
}
接口多实现出现的问题
- 首先,当实现多接口的时候,实现类必须重写所有的抽象方法,但是会出现抽象方法同名的情况,这样的情况,实现类只需实现一次抽象方法即可。
- 当默认方法重名时候,也必须重写一次,因为默认方法是继承下来的,必须重写。
- 静态方法不会冲突,访问各自接口的静态方法即可
- 常量冲突,用接口名称.常量调用。
重点优先级问题
当一个类既继承父类,又实现了多个接口时候,父类的成员方法和接口的方法重名。优先级是怎么划分的,父类优先于接口,毕竟是亲的。
接口的多继承
接口是可以多继承的,也就是说接口之间是可以多继承的,和继承类似使用extends关键字。
出现默认方法重名,子接口要重写默认方法,
子类重写默认方法时候,default不可以保留,子接口重写默认方法时default可以保留。
接口中多继承,无法定义成员变量,只能有常量,其值不可变,默认使用public static final 修饰
接口中没有构造方法,不能创造对象。
接口没有静态代码块。
多态
多态代表着同一种行为,具有多种的表现形式,继承和实现是多态的基础。
多态是什么
1.继承或者实现,
2.方法的重写,不重写无意义,都是一种行为,
3.父类引用指向子类的对象。
多态的实现
2
2
1
父类类型 变量名 = new 子类对象
2
变量名.方法名;
具体的过程:
2
2
1
调用方法的时候,使用父类类型的变量,调用方法,首先编译的时候会检查父类是否有该方法,如果没有,会报错,如果有会执行子类的重写方法
2
调用成员变量的时候,使用什么变量调用就使用哪个变量的值。
口诀:成员变量都看左,成员方法编译看左,运行看右。
2
2
1
使用多态的好处,不用定义子类的单独方法,首先用父类的类型变量,调用方法,本身自己是父类类型,都是抽象方法,没法调用,只能调用包含的子类的重写方法。很完美,这就是左面编译,有运行的概念,左面是父类的抽象方法,所以可以通过编译,但是子类的重写方法可以通过new的子类对象调用,
2
这就是静态绑定,和动态绑定。
引用类型转换
子类转成父类:这种叫向上转型,这种是默认的转型的,当父类引用一个子类的对象时候,就是向上转型。
父类转成子类:这种叫向下转型,这种是强制的转型,但是应该注意的是,只有是转过型的父类才可以成功转换回子类的对象。??????有问题是不是只有转过型的才可以向下转。
出现的问题:
在程序中,父类型的包含子类的对象想运行子类特有的方法,这就很尴尬,父类没有该方法,直接编译时候就会报错,所以想要使用子类特有方法就要向下转型。
转型很容易就转成别的类型,
使用instanceof关键字
父类变量名 instanceof 子类类型 ;
是就返回ture 不是返回false
12
12
1
public class Test {
2
public static void main(String[] args) {
3
// 向上转型
4
Animal a = new Cat();
5
a.eat();
6
7
if (a instanceof Cat){
8
Cat c = (Cat)a; c.catchMouse(); //调用的是Cat的catchMouse
9
}
10
else if (a instanceof Dog){ Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog的watchHouse }
11
}
12
}
equals重写
x
1
public boolean equals (Obejct object)
2
用来比较 本类 的两个对象是否在 逻辑上相等 , 而不是地址上相等
3
相等返回 true 反之false
4
该方法是 Object 定义 , 所有类都拥有该方法
5
6
equals 默认比较的是地址 子类如果有该需求 一定记得重写 equals
7
8
/**
9
* 如果有属性是引用数据类型 , 一定不能 == 来比较
10
* 而是调用属性对象的 equals 方法
11
*/
12
13
/**
14
* instanceof 关系运算符
15
* 使用格式 :
16
* 对象 instanceof 类名 ;
17
* 返回 布尔值
18
* 如果 对象是该类的对象 , 那么返回true 反之false
19
*
20
*/
21
22
/**
23
* 基本数据类型强转 : 可能会丢失数据
24
* 引用数据类型强转 : 可能会有类型不匹配异常 java.lang.ClassCastException
25
* 如果没有继承关系 不能强转
26
*/
27
28
@Override
29
public boolean equals(Object obj) {
30
if( this == obj)
31
return true;
32
33
// 判断 obj 是本类对象
34
if( !(obj instanceof Person) )
35
return false;
36
37
// 引用数据强转 经过判断之后可以放心的强转了
38
Person p = (Person)obj;
39
40
// 接下来是 具体的判断是否相等的 业务逻辑
41
if( this.age == p.age)
42
if(this.sex == p.sex)
43
return this.name.equals(p.name);
44
45
return false;
46
}
47
comparable实现
该接口已经出现 Comparable -> 又叫内部比较器
该方法也已经出现 public int compareTo(Object o);
只要类需要比较功能 , 那么就实现Comparable 接口
compareTo 方法学习
方法返回值是 int 的 , 正好对应了比较的 3 种情况
约定 : 正数(大于) 0(等于) 负数(小于)
10
1
/**
2
* 按照 age 进行比较
3
*/
4
@Override
5
public int compareTo(Object o) {
6
System.out.println("Person.compareTo()");
7
Person p = (Person)o;
8
int result = this.age - p.age;
9
return result;
10
}
1
/**
2
* 按照 sex 进行比较 boolean 不能直接 - , 可以把boolean 替换成 1 和 0 ;
3
*/
4
@Override
5
public int compareTo(Object o) {
6
Person p = (Person)o;
7
int result = this.sex ? 1 : 0 - (p.sex ? 1 : 0);
8
return result;
9
}
以上是关于07.多态,接口的主要内容,如果未能解决你的问题,请参考以下文章