抽象类特点
- 抽象类和抽象方法都使用 abstract 关键字进行声明。抽象类一般会包含抽象方法,抽象方法一定位于抽象类中。
- 抽象类和普通类最大的区别是,抽象类不能被实例化,需要继承抽象类才能实例化其子类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public abstract class AbstractClassExample {
protected int x;
private int y;
public abstract void func1();
public void func2() {
System.out.println("func2");
}
}
public class AbstractExtendClassExample extends AbstractClassExample {
@Override
public void func1() {
System.out.println("func1");
}
}
接口特点
- 接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。
- 从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。
- 接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。
- 接口的字段默认都是 static 和 final 的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public interface InterfaceExample {
void func1();
default void func2(){
System.out.println("func2");
}
int x = 123;
public int z = 0; // Modifier 'public' is redundant for interface fields
}
public class InterfaceImplementExample implements InterfaceExample {
@Override
public void func1() {
System.out.println("func1");
}
}
抽象类与接口的区别
区别
- 从设计层面上看,抽象类提供了一种 IS-A 关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。
- 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。
- 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。
- 接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。
如何选择
- 使用接口:
- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法;
- 需要使用多重继承。
- 使用抽象类:
- 需要在几个相关的类中共享代码。
- 需要能控制继承来的成员的访问权限,而不是都为 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/*要的都是对象具体类的作为参数传递的问题*/
class Student {
public void show() {
System.out.println("student.....show.............") ;
}
}
class StudentDemo {
public void method(Student s) {
s.show() ;
}
}
// 测试类
class ArgsDemo {
public static void main(String[] args) {
// 创建StudentDemo的对象
StudentDemo sd = new StudentDemo() ;
// 创建Student的对象
Student s = new Student() ;
// 调用方法
// sd.method(s) ;
sd.method(new Student()) ;
}
}
面向对象之抽象类名作为形式参数
- 案例
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/*抽象类作为参数的时候如何进行调用*/
abstract class Animal {
// 定义一个抽象方法
public abstract void eat() ;
}
// 定义一个类
class Cat extends Animal {
public void eat(){
System.out.println("吃.................") ;
}
}
// 定义一个类
class AnimalDemo {
public void method(Animal a) {
a.eat() ;
}
}
// 测试类
class ArgsDemo2 {
public static void main(String[] args) {
// 创建AnimalDemo的对象
AnimalDemo ad = new AnimalDemo() ;
// 对Animal进行间接实例化
// Animal a = new Cat() ;
Cat a = new Cat() ;
// 调用method方法
ad.method(a) ;
}
}
面向对象之接口名作为形式参数
- 案例
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/*接口作为参数的时候我们如何进行调用*/
interface Jump {
// 跳高接口
public abstract void jump() ;
}
// 定义一个子类
class JumpImpl implements Jump {
public void jump(){
System.out.println("jump.............................") ;
}
}
// 定义一个类
class JumpDemo {
public void method(Jump jump) {
jump.jump();
}
}
// 测试类
class ArgsDemo3 {
public static void main(String[] args) {
// 1. 创建JumpDemo对象
JumpDemo jd = new JumpDemo() ;
// 2. 调用method方法
// 对Jump进行间接实例化
Jump jump = new JumpImpl() ;
jd.method(jump) ;
}
}
面向对象之类名作为返回值类型
- 案例
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/*具体类作为返回值类型*/
class Student {
public void show() {
System.out.println("student....show.....................") ;
}
}
// 定义一个类
class StudentDemo {
public Student getStudent() {
return new Student() ;
}
}
// 测试类
class ReturnDemo {
public static void main(String[] args) {
// 创建StudentDemo的对象
StudentDemo sd = new StudentDemo() ;
// 调用 public Student getStudent()
Student s = sd.getStudent() ;
// 调用方法
s.show() ;
}
}
面向对象之抽象类名作为返回值类型
- 案例
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/*抽象类作为返回值类型*/
abstract class Animal {
public abstract void eat() ;
}
// 定义一个子类
class Cat extends Animal {
public void eat(){
System.out.println("吃..........................") ;
}
}
// 定义一个类
class AnimalDemo {
public static Animal getAnimal() {
// Animal a = new Cat() ;
// return a;
return new Cat() ;
}
}
// 测试类
class ReturnDemo2 {
public static void main(String[] args) {
// 调用AnimalDemo的getAnimal这个方法
Animal a = AnimalDemo.getAnimal() ;
// 调用方法
a.eat() ;
}
}
面向对象之接口名作为返回值类型
- 案例
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/*接口作为返回值类型*/
interface Jump {
public abstract void jump() ;
}
// 定义一个子类
class JumpImpl implements Jump {
public void jump(){
System.out.println("jum....................") ;
}
}
// 定义一个类
class JumpDemo {
public static Jump getJump() {
return new JumpImpl() ;
}
}
// 测试类
class ReturnDemo3 {
public static void main(String[] args) {
// 调用getJump方法
Jump jump = JumpDemo.getJump() ;
// 调用
jump.jump() ;
}
}