【334-357】抽象类和接口
2021-12-31 17:14:00 # JavaSE

抽象类

抽象类的理解

这里先放一个图片…

抽象类属于什么数据类型?

抽象类属于引用数据类型

抽象类怎么定义?

1
2
3
4
5
6
7
8
9
/* 抽象类的定义:
[修饰符列表] abstract class 类名{
类体
}
*/

abstract class A{

}

抽象类无法实例化对象

所以是用来被子类继承的

1
2
3
4
5
6
7
8
9
10
11
public class _335_抽象类无法实例化但有构造方法 {
public static void main(String[] args) {

/* A是抽象的; 无法实例化
new A();
*/
}
}
abstract class A{

}

final 和 abstract 不能联用

1
2
3
4
5
6
/*
非法的修饰符组合 final & abstract
final abstract class A{

}
*/

抽象类的子类可以是抽象类

也可以是非抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class A{

}
/*
子类B继承抽象类A,B可以被实例化
class B extends A{

}
*/

/*
抽象类的子类可以是抽象类
abstract class B extends A{

}
*/

抽象类无法实例化,但有构造方法

构造方法是供子类实现的

1
2
3
4
abstract class A{
public A() {
}
}

抽象方法表示没有实现的方法

特点1:没有方法体,以分号结尾;
特点2:修饰符有abstract;

1
2
3
4
5
6
abstract class B{
public void test1(){

};
public abstract void test2();
}

抽象类不一定有抽象方法,抽象方法必须出现在抽象类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class B{
public void test1(){

};
public abstract void test2();
}

/*
抽象方法必须出现在抽象类中
class C{
public abstract void test();
}
*/

非抽象类继承抽象类,必须将抽象类中的方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class _338_非抽象类继承抽象类必须将抽象方法实现 {
public static void main(String[] args) {
// 使用多态
// 父类型的引用指向子类型对象
// 面向抽象编程:
// 降低程序耦合度
// 提高程序扩展力
// 这种编程思想符合OCT原则
Animal a = new Bird();
// move()方法
// 编译的时候是Animal的
// 运行的时候是Bird的
a.move();

}
}

abstract class Animal{
public void die(){};
public abstract void move();
}

// 非抽象类继承抽象类需要实现抽象类中的抽象方法
class Bird extends Animal{
@Override
public void move() {
System.out.println("flying~");
}
}

// 抽象类继承抽象类可以继承父类的抽象方法
abstract class Bird2 extends Animal{

}

Java没有方法体的方法都是抽象方法?

答:不是。
Object类中有方法如下:

1
public native int hashCode();

底层调用C++的动态链接库,表示调用JVM本地程序

接口的基础语法

总结

1、接口是一种“引用数据类型”
2、接口是完全抽象的。
3、接口怎么定义:[修饰符列表] interface 接口名{}
4、接口支持多继承。
5、接口中只有常量+抽象方法
6、接口中所有的元素都是pub1ic修饰的
7、接口中抽象方法的public abstract可以省略。
8、接口中常量的public static final可以省略。
9、接口中方法不能有方法体。
10、一个非抽象的类,实现接口的时候,必须将接口中所有方法加以实现。
11、一个类可以实现多个接口-
12、extends和implements可以共存,extends在前,implements在后。
13、使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象)。

接口属于什么数据类型?

引用数据类型,编译生成.class字节码文件

接口是完全抽象的

抽象类是半抽象的,或者说接口是特殊的抽象类。

接口怎么定义

1
2
3
4
// [修饰符列表] interface 接口名{}
interface C{

}

接口支持多继承-

1
2
3
4
5
6
7
8
9
10
11
12
interface C{

}

interface D{

}

// 接口支持多继承
interface E extends C,D{

}

接口中只有常量+抽象方法。

1
2
3
4
5
6
interface Math1{
// 常量
public static final double PI = 3.1415;
// 抽象方法
public abstract int sum(int a, int b);
}

接口中所有的元素都是public修饰的

都是公开的。

接口中抽象方法的public abstract可以省略

1
2
3
4
5
6
interface Math1{
// 接口当中都是抽象方法
// public abstract 可以省略
// public abstract int sum(int a, int b);
int sum(int a, int b);
}

接口中常量的public static final可以省略

1
2
3
4
5
6
interface Math1{
// 常量
// public static final可以省略
// public static final double PI = 3.1415;
double PI = 3.1415;
}

接口中方法不能有方法体

1
2
3
4
5
6
7
interface Math1{
/*
接口抽象方法不能有方法体,毕竟是抽象的
int add(){

};*/
}

类实现接口要实现所有方法

使用implements关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class _345_类实现接口要实现所有方法 {
public static void main(String[] args) {

}
}

interface Math2{
double PI = 3.1415;
int sum(int a, int b);
int sub(int a, int b);
}

// 抽象类继承,不实现方法也可行
abstract class Math2Impl2 implements Math2{

}

// 非抽象类implements接口需要实现接口中所有的方法
class Math2Impl implements Math2{
@Override
public int sum(int a, int b) {
return a + b;
}

@Override
public int sub(int a, int b) {
return a - b;
}
}

接口中的方法都是public的,类实现时修饰符只能写public

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class _346_接口中的方法都是public{
}

interface Math3{
double PI = 3.1415;
int sum(int a, int b);
int sub(int a, int b);
}

// 非抽象类implements接口需要实现接口中所有的方法
class Math2Impl3 implements Math3{
/*
接口中的方法是public,
这里的修饰符访问权限只能更高,
也就是public
@Override
int sum(int a, int b) {
return a + b;
}
*/
@Override
public int sum(int a, int b) {
return a + b;
}

@Override
public int sub(int a, int b) {
return a - b;
}
}

接口和多态的联合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class _347_接口和多态的联合使用 {
public static void main(String[] args) {
// 面向接口编程
Math4 p = new Math2Impl4();
// 调用接口里面的方法
System.out.println(p.sum(1,2));
System.out.println(p.sub(3,2));
}
}

interface Math4{
double PI = 3.1415;
int sum(int a, int b);
int sub(int a, int b);
}

class Math2Impl4 implements Math4{
@Override
public int sum(int a, int b) {
return a + b;
}

@Override
public int sub(int a, int b) {
return a - b;
}
}

一个类可以实现多个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class _348_一个类可以实现多个接口 {
public static void main(String[] args) {
// 多态的使用
F f = new H();
G g = new H();
f.m1();
// 强制转换,有继承关系强转
( (G)f ).m2();

// --------------------------

// 接口之间强制转化在没有继承关系下也可以
// 但是运行时可能会出现ClassCastException异常
// 编译没问题,运行有问题
J j = new K();
I i = (I)j;

// 转型建议加判断
if(j instanceof K){
I ii = (I)j;
}
}
}

interface F{
void m1();
}

interface G{
void m2();
}

// 一个类可以实现 多个接口
// 需要实现所有方法
// 弥补单继承的缺陷
class H implements F, G{
@Override
public void m1() {
System.out.println("m1");
}

@Override
public void m2() {
System.out.println("m2");
}
}

interface I{}
interface J{}
class K implements J{};

extends和implements同时出现

extends 在前 implements 在后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class _349_extendsimplements同时出现 {
public static void main(String[] args) {
Flyable f1 = new Cat();
f1.fly();

Flyable f2 = new Pig();
f2.fly();

}
}

class Animal1{

}

// 可飞翔的接口
// 能插拔的接口
interface Flyable{
void fly();
}

// extends 在前 implements 在后
// 给 猫类 继承 动物类 再插上 Flyable 接口
class Cat extends Animal1 implements Flyable{
@Override
public void fly() {
System.out.println("cat flying~");
}
}

// 蛇类,不飞,就不插 Flyable 接口
class Snake extends Animal1{}

// 想飞就插接口
class Pig extends Animal1 implements Flyable{
@Override
public void fly() {
System.out.println("pig flying~");
}
}

// 不写extends默认继承Object类
class Fish /*extends Object*/ implements Flyable{
@Override
public void fly() {
System.out.println("fish flying~");
}
}

接口在开发中的作用

解耦合!!!

最先定下接口
然后
调用者调用接口
实现者实现接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public class _351_接口在开发中的作用 {
public static void main(String[] args) {
// 创建厨师对象
Menu chinaChef = new ChinaChef();
// 创建顾客对象 传入中国厨师的菜单
Customer customer = new Customer(chinaChef);
// 顾客点菜
customer.order();

// 改成西餐
Menu americaChef = new AmericaChef();
customer = new Customer(americaChef);
customer.order();
}
}

/*
* **解耦合**
* 接口的使用离不开多态
* 降低程序的耦合度,提高程序扩展力,符合OCP开发原则
* */

class Customer{
// ***面向接口编程
// Menu中可以有 ChinaChef 或 AmericaChef 做的 food
// 属性私有化必定养成习惯 get set
private Menu menu;

/*
这样写就把 Customer 吃的菜种类写死了
1.
ChinaChef cc;
2.
AmericaChef dd;
*/

public Customer(){}
public Customer(Menu menu) {
this.menu = menu;
}

public Menu getMenu() {
return menu;
}

public void setMenu(Menu menu) {
this.menu = menu;
}

// 点菜
public void order(){
// 先拿菜单
Menu menu = this.getMenu();
// 点菜
menu.food1();
menu.food2();
}

}

// 菜单
interface Menu{
void food1();
void food2();
}

// 厨师实现菜单接口
class ChinaChef implements Menu{
@Override
public void food1() {
System.out.println("ChinaChef food1");
}

@Override
public void food2() {
System.out.println("ChinaChef food2");
}
}

class AmericaChef implements Menu{
@Override
public void food1() {
System.out.println("AmericaChef food1");
}

@Override
public void food2() {
System.out.println("AmericaChef food2");
}
}

类与类之间的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class _356_类与类之间的关系 {
}

/*
* is a, has a, like a
* is a:
* Cat is a Animal
* 表示“继承关系”
* A extends B{}
*
* has a:
* I has a pen
* 关联关系通常以“属性”形式存在
* A{
* B b;
* }
*
* like a:
* Chef like a Menu
* 表示“实现关系”
* 类实现接口
* A implements B{}
*
* */

接口和抽象类在语法上的区别

  • 在语法上的区别:
  • 抽象类是版抽象的
  • 接口是完全抽象的
  • 抽象类中没有构造方法
  • 接口中没有构造方法
  • 接口和接口之间支持多继承
  • 类和类之间只能单继承
  • 一个类可以同时实现多个接口
  • 一个抽象类只能继承一个类(单继承)
  • 接口中只允许出现常量和抽象方法
  • 以后接口使用的比较多
  • 接口一般都是对“行为”的抽象
Prev
2021-12-31 17:14:00 # JavaSE
Next