抽象类
面向对象编程的核心就是面向抽象编程,一般在开发过程中依赖抽象,不依赖具体
简介抽象类
包含抽象方法的类就叫做抽象类。抽象类不允许直接创建实例,只能由子类提供方法实现后才能通过子类创建对象
抽象方法就是指没有方法体的方法,方法只做声明,没有具体的实现。抽象方法必须在子类中提供具体是实现
-
抽象类中可以包含抽象方法,不是必须包含抽象方法
语法:
public abstract class Animal{} //abstract class用于声明抽象类
public class Dog extends Animal{}
Animal animal = new Dog(); //如果直接new Animal则语法报错 (抽象类不允许直接创建实例,只能由子类提供方法时间后才能通过子类创建对象)
特点:
-
包含抽象方法的类就是抽象类,但是抽象类可以没有抽象方法
public abstract class (Animal){
//方法是由具体实现的,不过是空实现,不是没有方法体
public void pp(){}
public abstract void cc();//注意抽象方法不能包含方法体
}
-
抽象类不能直接进行实例化,只能定义具体实现的子类后进行new操作
-
抽象类中可以定义构造器,也可以不定义构造器,由系统自动提供无参构造器
-
抽象类不能直接进行new操作和有无构造器没有关系
-
-
抽象类和普通类一样可以定义成员方法和成员属性,以及构造器和析构器。只是抽象类允许包含抽象方法
-
普通类继承抽象类,则必须针对抽象类中的所有抽象方法提供具体实现
public abstract class Animal{
private String name;
protected int age;
//构造器
public Animal(){}
public Animal(int age){}
//普通成员方法
public void sleep(){
System.out.println("闭着眼睛...")
}
public abstract void walk(); //抽象方法
}
public abstract class mammals extends Animal{
//没有针对行走这个方法提供实现,则当前子类只能是抽象类
}
public class class Person extends mammals{
public void walk(){} //允许空实现,但是不能没有实现
}
-
在具体应用中一般抽象类用于定义规范或者通用的方法
-
通用方法是为了共享,避免子类重复定义
-
规范是为严格要求子类必须提供实现
-
抽象类的特点
-
方法只有声明而没有具体的实现,则方法就是抽象方法
-
不是空实现方法体,是没有方法体
-
需要使用abstract修饰,否则语法报错
-
抽象方法必须定义在抽象类中,该类也必须使用abstract修饰
-
-
抽象方法只能使用范围限定词中的public/protected/package默认,不能使用private
-
public void pp(){} 这是一个包含空实现的方法,不是抽象方法
-
public void pp(); 这是一个没有方法实现的方法。在抽象类中要求必须使用abstract修饰
public abstract void pp();
-
-
不允许定义抽象构造器
public abstract Animal(); //语法报错
-
抽象类中可以定义构造器,也可以不定义构造器,由系统自动提供默认的无参构造器。但是如果自定义构造器,不允许构造器private
abstract class Animal{ private Animal(){} } class Dog extends Animal{ //因为Animal中只有一个private构造器,所以Dog构造对象时,不能调用父类构造器所以报错 }
-
如果需要定义私有构造器,则必须提供带参的得私有构造器
abstract class Parent { private Parent2() {} public Parent2(int age) { //this(); } } class Son extends Parent { public Son2() { super(10); } }
-
-
抽象类或者抽象方法不允许为final
-
final类不允许定义子类,则不能定义子类
-
final方法不允许子类中覆盖定义,所以不能定义final抽象方法
-
-
抽象类中可以定义静态方法
public class Test3 { public static void main(String[] args) { Parent3.pp(); // 没有办法直接使用Parent3对象调用 Parent3 p3=new Son3(); p3.pp(); } } abstract class Parent3 { public static void pp() { System.out.println("Parent...pp"); } } class Son3 extends Parent3 { }
-
不允许定义抽象静态方法
abstract class Parent3 { public static abstract void pp(); //语法报错 }
-
可以使用抽象类直接调用静态方法
-
-
抽象类不能直接创建对象,只能通过继承的方式定义子类,然后创建子类对象。子类对象可以赋值给抽象类声明的变量
-
抽象类中除了可以定义抽象方法,也可以定义非抽象方法
问题
抽象类不能实例化,是否是因为抽象类中没有定义构造器所导致?
-
抽象类不能实例化是语法规则,和有没有构造器没有关系
-
抽象类中可以定义构造器,也可以不定义构造器。如果不定义构造器则系统自动提供无参构造器
-
创建子类对象时,抽象父类的构造器也会自动被调用执行
抽象类不能实例化,是否因为调用抽象方法没有意义?
抽象类可以包含抽象方法,也可以没有抽象方法。没有抽象方法时,抽象类也不能实例化。抽象类必须由子类覆盖定义了父类的所有抽象方法后,子类才可以实例化,否则这个子类还是抽象类
抽象类的使用场景
-
当一个类中的一个或者多个方法是抽象方法时
-
当一个类为抽象类的子类时,并没有为所有的抽象方法提供实现或者提供方法主体时
-
当一个类实现一个接口时,并没有为接口中的所有方法提供实现细节或者提供方法体时
抽象类和普通类
-
抽象类不能直接实例化,只能通过子类进行实例化;普通类可以直接实例化
-
抽象类允许包含抽象成员方法;普通类中不允许包含抽象方法
-
抽象类不允许被密封。final密封类不能被继承,防止恶意的派生
应用场景
何时使用:有一些通用的方法
如何解决:将这些通用算法抽象出来。
1、有多个子类共有的方法,且逻辑相同。
2、重要的、复杂的方法,可以考虑作为模板方法。
优点
1、封装不变部分,扩展可变部分。
2、提取公共代码,便于维护。
3、行为由父类控制,子类实现。
缺点
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
抽象类的作用
主要用途是进行类型的隐藏。构造出一个固定的一组行为的抽象描述,但是这组行为能够有任意个可能的具体实现方式
抽象类一般用来表征问题域的分析,设计中经常会先获取抽象类,然后再定义确定的具体类
OOP的核心就是面向抽象编程
-
在父类中固化算法骨架,在子类中实现特殊的方法
常见问题
抽象类种有构造器?
-
有,用于给子类对象进行初始化
-
new子类时抽象父类的构造器一定会被执行
抽象类可以不定义抽象方法?
-
可以的,但是一般较少出现
-
目的就是不允许构建该类对象,只能被子类继承
-
通过子类才能构建抽象父类的对象
抽象类一定是父类?
-
是的
-
因为需要子类提供父类抽象方法的实现,才可以进行实例化
创建对象时,加载的顺序
-
先加载父类
-
处理父类的静态属性和静态初始化块,两者地位相等,执行顺序取决于定义顺序
-
静态代码块和静态方法一致,要求只能直接访问静态成员
-
如果需要在静态代码块和静态方法中访问非静态成员则必须构建对象
-
-
加载子类
-
处理子类的静态属性和静态初始化块,两者地位相等,执行顺序取决于定义顺序
-
静态代码块和静态方法一致,要求只能直接访问静态成员
-
如果需要在静态代码块和静态方法中访问非静态成员则必须构建对象
-
-
先加载父类
-
成员属性和初始化块,两者地位相等,执行顺序取决于定义顺序
-
父类构造器
-
-
加载子类
-
成员属性和初始化块,两者地位相等,执行顺序取决于定义顺序
-
子类构造器
-