在项目开发中,一定不要用一个类继承一个已经实现好的类,而只能继承抽象类和接口。
对象的多态性核心本质在于方法的覆写,如果子类没有进行方法的覆写,有些不符合操作,所以如果要对子类的方法做一些强制的要求,就必须采用抽象类。
1.抽象类的概念
抽象类在普通类的基础上扩充了一些抽象方法而已。抽象方法指的是 指声明未实现(就是没有方法体),用abstract修饰。
abstract class A {
private String msg = "111111";
public void print(){
System.out.println("22222222");
}
public abstract void fun () ; //抽象方法(没有方法体)
}
public class TestDemo{
public static void main(String args[]){
}
}
抽象类就是比普通类多了一些抽象方法而已,并且抽象方法没有方法体。
抽象类中包含有抽象方法,抽象方法没有方法体,就是不知道具体的实现,而产生实例化对象,意味着可以调用类中的所有操作,但是没有方法体不能调用。
所有的抽象类必须有子类;
抽象类的子类必须覆写抽象类中的全部抽象方法;
抽象类的对象可以通过对象多态性,利用其子类进行实例化;
抽象方法 大都使用public权限
范例:抽象方法实现
abstract class A {
private String msg = "111111";
public void print(){
System.out.println("22222222");
}
public abstract void fun () ; //抽象方法(没有方法体)
}
class B exttends A {
public abstract void fun () {
System.out.println("333333333333");
}
}
public class TestDemo{
public static void main(String args[]){
A a = new B();
a.fun();
}
}
结果:333333333
从开发角度来说,上述代码没有问题,但是对于抽象类必须进行一点说明
可能会遇到以下情况:
abstract class A {
private String msg = "111111";
public void print(){
System.out.println("22222222");
}
public static getInstance() { //geInstance() 取的实例化对象
class B exttends A {
public abstract void fun () {
System.out.println("333333333333");
}
}
return new B();
}
public abstract void fun () ; //抽象方法(没有方法体)
}
public class TestDemo{
public static void main(String args[]){
A a = new B();
a.fun();
}
}
上述代码属于非正常模式,但是对于封装性是有好处的,
2、抽象类使用限制
(1)抽象类中依旧有构造方法,并且子类也会遵守子类实例化对象的流程,实例化子类对象也一定先会调用父类构造方法。
范例:在抽象类中定义构造方法
abstract class Person {
private String name;
private int age;
public Person () {
System.out.print("**********");
}
public abstract String getInfo() ;
}
class Stuedent extends Person{
private String school;
public student() {
System.out.print("###########");
}
public String getInfo(){
return null;
}
}
public class TestDemo{
public static void main(String args[]){
new student();
}
}
结果: ***************
###########
如果父类中没有无参构造,那么子类就必须通过super指明父类调用的构造方法,
抽象类中存在构造方法也很好理解,抽象类中也含有属性,所有的属性在对象实例化时要进行空间开辟,对象的实例化必须需要构造方法。
对象实例化操作需要以下步骤
进行类的加载;
进行类对象的空间开辟;
进行类对象中的属性初始化(构造方法);
注意一下代码分析:
abstract class A {
public A() { //构造方法 3、调用父类构造方法(2)
this,print(); //调用抽象方法 4、调用被子类覆写过的方法
}
public abstract void print() ; //抽象方法
}
class B extends A{
private int num = 100;
public B(int num) { //2、调用子类实例化对象
super(); //3、隐含一行语句,实际想要调用父类构造方法(1)
this.num = num;//7、为了类中的属性初始化
}
public abstract void print(){ //5、此时子类对象的属性还没有被初始化
System.out.println(this.num); //6、内容其数据类型的默认值 此时已经输出,输出之后才到第七步
}
}
public class TestDemo{
public static void main(String args[]){
new B(30); //1、实例化对象
}
}
结果:0
如果构造方法没有执行,那么类中的属性为其数据类型的默认值。
(2)抽象类中允许不定义任何抽象方法,但是抽象类对象仍然无法直接进行实例化处理;
(3)抽象类一定不能使用final声明,也不能用private;
(4)抽象类也分为内部抽象类和外部抽象类;
外部抽象类使用了static是语法错误,但是内部抽象类可以使用static
从一般设计角度来说,以上问题不会经常出现。
3、抽象类的模板设计模式
抽象类的最大的特点在于强制规定了子类的实现结构,并且抽象类更多的情况下还可以起到一个模板作用。
abstract class Action {
public static final int EAT_FLAG = 1;
public static final int SLEEP_FLAG = 5;
public static final int WORK_FLAG = 10;
public void command(int cmd){
switch (cmd) {
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
case EAT+SLEEP+WORK:
this.eat();
this.work();
this.sleep();
}
}
//不具体实现,行为定义好
public abstract void eat() ;
public abstract void sleep() ;
public abstract void work() ;
}
class Human extends Action{
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
public void work() {
System.out.println("工作");
}
}
class Pig extends Action{
public void eat() {
System.out.println("猪猪吃饭");
}
public void sleep() {
System.out.println("猪猪睡觉");
}
public void work() {}
}
class Robot extends Action{
public void eat() {
System.out.println("机器吃饭");
}
public void sleep() {}
public void work() {
System.out.println("机器工作");
}
}
public class TestDemo {
public static void main(String args[]) {
fun(new Huanm());
fun(new Pig());
fun(new Robot());
}
public static void fun(Action action){
action.command(Action.EAT + Action.SLEEP + Action.WORK);
}
}
通过此程序定义结构可以发现,抽象类在实际的使用过程中会定义一些固化模式,它接受几种特定的指令,指令的实现由子类实现。
总结:
抽象类的使用必须要通过子类进行对象的实例化处理。