在了解抽象类与接口之前,我们需要首先明白面向对象的三大特征:封装、多态与继承
1.1 封装
封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。就好像我们看不到挂在墙上的空调的内部的零件信息(也就是属性),但是可以通过遥控器(方法)来控制空调。如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。就好像如果没有空调遥控器,那么我们就无法操控空凋制冷,空调本身就没有意义了(当然现在还有很多其他方法 ,这里只是为了举例子)。

public class Student {
private int id;//id属性私有化
private String name;//name属性私有化

//获取id的方法
public int getId() {
return id;
}

//设置id的方法
public void setId(int id) {
this.id = id;
}

//获取name的方法
public String getName() {
return name;
}

//设置name的方法
public void setName(String name) {
this.name = name;
}

}
1.2. 继承
不同类型的对象,相互之间经常有一定数量的共同点。例如,小明同学、小红同学、小李同学,都共享学生的特性(班级、学号等)。同时,每一个对象还定义了额外的特性使得他们与众不同。例如小明的数学比较好,小红的性格惹人喜爱;小李的力气比较大。继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承,可以快速地创建新的类,可以提高代码的重用,程序的可维护性,节省大量创建新类的时间 ,提高我们的开发效率。

关于继承如下 3 点请记住:

子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。(以后介绍)。
1.3. 多态
多态,顾名思义,表示一个对象具有多种的状态。具体表现为父类的引用指向子类的实例。

多态的特点:
对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
对象类型不可变,引用类型可变;
方法具有多态性,属性不具有多态性;
引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
多态不能调用“只在子类存在但在父类不存在”的方法;
如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。

import java.util.Scanner;

//基类Shape建立了一个通用接口,所有(几何)形状都可以描绘和删除。
class Shape {
void draw() {
}
void erase() {
}
}

//派生类覆盖了draw方法,为每种特殊类型的几何形状都提供了独一无二的行为。
class Circle extends Shape {
@Override // @Override注解,表示覆盖父类方法
void draw() {
System.out.println("Circle.draw()");
}
@Override
void erase() {
System.out.println("Circle.erase()");
}
}
class Square extends Shape {
@Override
void draw() {
System.out.println("Square.draw()");
}
@Override
void erase() {
System.out.println("Square.erase()");
}
}
class Triangle extends Shape {
@Override
void draw() {
System.out.println("Triangle.draw()");
}
@Override
void erase() {
System.out.println("Triangle.erase()");
}
}
//下面对动态绑定进行测试如下:
public class Example7_100 {
public static void main(String[] args) {
	Scanner reader = new Scanner(System.in);
Shape[] shape = new Shape[3];
int n;
for (int i = 0; i < shape.length; i++) {
n = reader.nextInt();
switch (n) {
case 0:
shape[i] = new Circle();
break;
case 1:
shape[i] = new Square();
break;
case 2:
shape[i] = new Triangle();
}
}
for (Shape oneS : shape) { // 增强for循环,应在JDK 5及其以上版本运行
//TODO:调用draw()方法	
oneS.draw();
}
}
}

1.3.1. 在一个静态方法内调用一个非静态成员为什么是非法的?
由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

1.3.2. 静态方法和实例方法有何不同
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。

静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

//以上内容来自https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/basis

抽象类其实就是包含着抽象方法的类,抽象方法即为:在一个类里面有成员函数和成员变量,成员函数的组成是:访问修饰符+返回值类型+函数名+参数表+函数体
例如
public void fun () { } 缺一不可。
抽象函数顾名思义就是函数的抽象,它与函数的关系就好比类与对象的关系一样。
抽象类的组成是:
访问修饰符+abstract关键字+返回值类型 +函数名+参数表+分号
例如:
public abstract void fun() ; //区别多了一个abstract关键字且没有函数体,取而代之的是分号。
2.1抽象方法
只有在抽象类中才能定义抽象方法,所以抽象类也应该有abstract关键字。
格式是abstract + class +类名
例如 :abstract class people {} //抽象方法没有分号,也不能实例化对象
抽象方法存在的意义只能被类继承,然后重写它的抽象方法之后这个类才可以实例化对象。类是对象的抽象,那么抽象类就是类的抽象。

2.2抽象方法和抽象类的意义
抽象方法是抽象类的核心,有了抽象方法的抽象类才有灵魂。抽象方法的意义在于:当我们继承了一个抽象类的时候,抽象方法的存在迫使我们必须要重写抽象方法才能实现类的使用。

补充:重载和重写的区别
重载:
(1)就是同样的一个方法能够根据输入数据的不同,做出不同的处理
(2)发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。

重写:
(1)当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法
(2)返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
(3)如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
(4)构造方法无法被重写
重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变

2.3抽象类和接口的联系与区别
(1)抽象类可以存在普通成员函数,而接口中只能存在public abstract 方法。
(2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。
(3)抽象类只能继承一个,接口可以实现多个。

//如有问题请致邮箱 rainhao@223@gmail.com