Java面向对象—抽象类和接口
一、抽象类
抽象的定义:
我们在日常生活中,经常通过总结一些事物的共性来对事物进行分类,这种共性可能是一些相同的属性,也可能是一些相同的动作。通过总结,我们能够清晰的划分事物的分类。同样,在程序设计中,我们将拥有相同行为,但是不同表现形式的行为进行抽象,描绘出的方法,就称之为抽象方法,那么包含抽象方法的类,就是抽象类。
- 抽象方法:所谓的抽象方法,是指具有相同行为,但是不同分类的行为又有不同表现形式的方法,那么我们声明了方法,但又不需要具体实现方法内容的方法,称之为抽象方法。从语法结构上讲,就是通过abstract关键字来修饰的方法。
public abstract void jiao();
- 抽象类:在《java编程思想》中,是这么描述抽象类的,“包含抽象方法的类是抽象类”,我们可以理解为,这个类如果包含抽象方法,那么这个类就一定是个抽象类,但是,抽象类中的方法,不一定全都是抽象方法。
public abstract class Dog {
public abstract void jiao();
}
public abstract class Dog {
public abstract void jiao();
public void pao() {
System.out.println("狗可以跑!");
}
}
抽象类的使用:
我们可以这样理解,抽象方法在抽象类中,那么当使用抽象类的对象是,是无法直接使用方法的,所以我们只能通过继承的方式具体化一个抽象类的具体形象,就好像我们在欣赏一幅抽象派的画一样,我们需要在脑海中具象化一个具体的内容,来赋予这幅画的真实含义。我们的抽象类也是一样,需要具体化一个内容来描述抽象类。
//抽象类--狗
public abstract class Dog {
public abstract void jiao();
}
//狗类的继承类---二哈
public class ErHa extends Dog {
@Override
public void jiao() {
System.out.println("二哈边叫边拆家");
}
}
总结:当我们使用一个类去继承一个抽象类时,那么我们就要赋予这个抽象类中所描述的方法以具体实现效果,也就是我们的子类需要重写父类的抽象方法。但有些时候,我们的子类也不确定这个方法该怎么实现,那么我们就把子类也设计成为抽象类,基于Java中的多层继承,由子类的子类去实现这个方法。子子孙孙无穷匮也!
//抽象类--狗
public abstract class Dog {
public abstract void jiao();
}
//狗类的继承类---二哈
public abstract class ErHa extends Dog {
public abstract void jiao();
}
//灰色二哈
public class HuiErHa extends ErHa {
@Override
public void jiao() {
System.out.println("灰色二哈边叫边拆家边把自己弄脏");
}
}
抽象的注意事项:
- 抽象类和抽象方法必须使用abstract关键字修饰
- 抽象类中不一定有抽象方法,但是有抽象方法的一定在抽象类中
- 抽象类不能实例化 (实例 = 对象) [也就是不能创建对象],如果非要实例化,可以通过多态的形式创建,也就是 父类引用指向子类对象
- 抽象类的子类必须重写父类(抽象类)中所有的抽象方法或将自己也变成一个抽象类
二、接口
接口的定义:
接口(英文:Interface),在Java中是一个抽象类型,属于引用数据类型,是抽象方法的集合,接口通常以interface来声明。
个人的理解,接口是一个特殊的类,也是一种特殊的数据类型,它比抽象类更加抽象,是一种纯概念的定义。通常使用接口来定义类所需要的行为(方法)。
定义接口:Java中使用interface关键字定义接口,定义方式与类相同
[访问修饰符] interface 接口名{}
//定义狗类接口
public interface IDog {
//狗类有叫的行为
public void jiao();
//狗类有跑的行为
public void pao();
//狗类有吃的行为
public void eat();
}
接口的使用:类与类通过继承关系来实现,类与接口之间使用implements关键字实现,类与接口称之为实现。
[访问修饰符] class 类名 implements 接口名称{}
//金毛作为狗类的一员
public class JinMao implements IDog{
@Override
public void jiao() {
}
@Override
public void pao() {
}
@Override
public void eat() {
}
}
接口的特点:
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。所以接口中只能存在抽象方法(JDK1.8前)。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
接口与类的关系:
- 接口与接口之间的关系:接口与接口之间可以通过继承来实现父子接口的关系。接口继承接口使用extends关键字,并且接口可以多继承接口。
//动物接口
public interface IAnimal {
}
public interface IDog extends IAnimal{
//狗类有叫的行为
public void jiao();
//狗类有跑的行为
public void pao();
//狗类有吃的行为
public void eat();
}
- 接口与类之间的关系:类可以实现接口,并且在实现时要实现接口中的所有抽象方法,如果接口继承了其他接口,实现类也要实现父类接口中的所有抽象方法。实现类可以实现多个接口,从而实现多继承。
//动物接口
public interface IAnimal {
//动物有睡觉的行为
public void sleep();
}
//定义狗类接口
public interface IDog extends IAnimal{
//狗类有叫的行为
public void jiao();
//狗类有跑的行为
public void pao();
//狗类有吃的行为
public void eat();
}
//金毛作为狗类的一员
public class JinMao implements IDog{
@Override
public void jiao() {
}
@Override
public void pao() {
}
@Override
public void eat() {
}
@Override
public void sleep() {
}
}
- 接口类型的使用:在 Java
中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。依据多态的特性,我们可以定义接口类型的变量,实例化实现类对象
接口和抽象类的区别: - 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final
类型的,所以一般不会在接口中定义成员。 - 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
Java中的多继承:
Java中不支持像C++那样的多继承,类与类之间的关系也仅仅是多层继承,但是我们在实际项目中会遇到一个类有多种表现形态的时候,我们就会通过接口来实现这种多继承。接口最常见的使用方法是一种策略设计,相同的行为,不同的展现形式,使得接口更加美妙。
面向接口编程:
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。所以面向对象是面向接口的基础。