面向对象编程的核心就是面向抽象编程,一般在开发过程中依赖抽象,不依赖具体
public class A{ public void pp(Pig pig){}//如果使用具体类,则不具备灵活性。如果需要使用Cat,则只能修改源代码 } public class B{ public void pp(Animal obj){}//调用方法时实际上可以传入任何Animal的子类,例如Pig或者Cat } class Animal{} class Pig extends Anima1{} class Cat extends Animal{}
包含抽象方法的类叫做抽象类。抽象类不允许直接创建实例,只能由子类提供方法实现后才能通过子类创建对象
抽象方法就是指没有方法体的方法,方法只做声明,没有具体的实现。抽象方法必须在子类中提供具体实现
public abstract class Animal{} public class Dog extends Animal{} Animal an=new Dog();//如果直接new Animal则语法报错
public abstract class Animal { //方法时有具体实现的,不过是空实现,不是没有方法体 public void pp(){} public abstract void cc();//抽象方法,注意抽象方法不能包含方法体{} }
抽象类不能直接进行new操作,只能定义具体实现的子类后进行new操作
抽象类中可以定义构造器,也可以不定义构造器,由系统自动提供无参构造器
抽象类不允许new操作,和有没有构造器无关
public abstract class Animal{}//abstract class用于声明抽象类 public class Pig extends Animal{}//具体类必须实现了抽象类中所有抽象方法,否则这个类还是抽象类 Animal an=new Pig();
public abstract class 动物{ private String name; protected int age; //构造器 public 动物(){} public 动物(int age){} //普通成员方法 public void 碎觉(){ System.out.println("闭着眼睛..."); public abstract void 行走();//抽象方法 } public abstract class 哺乳动物 extends 动物{ //没有针对行走这个方法提供实现,则当前子类只能是抽象类 } public class 人类 extends 哺乳动物{ public void 行走(){}//允许空实现,但是不能没有实现 }
在具体应用中一般抽象类用于定义规范或者通用的方法
方法只有声明而没有具体的实现,则方法就是抽象方法
抽象方法只能使用范围限定词中的public/protected/package默认,不能使用private
public void pp(){}
这是一个包含空实现的方法,不是抽象方法public void pp();
这是一个没有方法实现的方法。在抽象类中要求必须使用abstract修饰public abstract void pp();
不允许定义抽象构造器public abstract Animaml();
语法报错
abstract class Animal{ private Animal(){} } class Dog extends Animal{ //因为Anima1中只有一个private构造器,所以Dog构造对象时,不能调用到父类构造器所以报错 }
abstract class Parent2 { private Parent2(){} public Parent2 (int age) { //this(); } } class Son2 extends Parent2 { public Son2() { super(10); } }
抽象类或者抽象方法不允许为final
抽象类中可以定义静态方法
public class Test1 { 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 { //The abstract method dd in type Parent3 can only set avisibility modifier,one of public or protected public static abstract void dd();//不允许使用abstract }
可以使用抽象类直接调用静态方法
抽象类不能直接创建对象,只能通过继承的方式定义子类,然后创建子类对象。子类对象可以赋值给抽象类声明的变量Animal a=new Dog();
抽象类中除了可以抽象方法,也可以有非抽象方法
问:抽象类不能实例化,是否是因为抽象类中没有定义构造器所导致?
答:1、抽象类不能实例化是语法规则,和有没有构造器没有关系;
2、抽象类中可以定义构造器,也可以不定义构造器。如果不定义构造器则系统自动提供无参构造器;
3、创建子类对象时,抽象父类的构造器也会自动被调用执行。
问:抽象类不能实例化,是否因为调用抽象方法没有意义?
答:抽象类可以包含抽象方法,也可以没有抽象方法。没有抽象方法时,抽象类也不能实例化。抽象类必须由子类覆盖定义了父类的所有抽象方法后,子类才可以实例化,否则这个子类还是抽象类。
问:抽象类种有构造器?
答:有,用于给子类对象进行初始化
;new子类时抽象父类的构造器一定会被执行
问:抽象类可以不定义抽象方法?
答:可以的,但是一般较少出现;目的就是不允许构建该类对象,只能被子类继承;通过子类才能构建抽象父类的对象
问:抽象类—定是父类?
答:是的。因为需要子类提供父类抽象方法的实现,才可以进行实例化创建对象时,加载的顺序:
先加载父类
加载子类
处理子类的静态属性和静态初始化块,两者地位相等,执行顺序取决于定义顺序。
静态代码块和静态方法一致,要求只能直接访问静态成员
如果需要在静态代码块和静态方法中访问非静态成员则必须构建对象
先加载父类
加载子类
成员属性和初始化块,两者地位相等,执行顺序取决于定义顺序
子类构造器
主要用途时进行类型的隐藏。构造出一个固定的一组行为的抽象描述,但是这组行为能够有任意个可能的具体实现方式。
public void pp(动物obj){ obj.work(); obj.公共方法(); public abstract class 动物{ public void 公共方法(){ 具体实现; } public abstract void work(); class 狗 extends 动物{ public void work(){ System.out.println("看大门!"); } }
抽象类一般用来表征问题域的分析,设计种经常会先获取抽象类,然后再定义确定的具体类OOP的核心就是面向抽象编程
在父类种固化算法骨架,在子类种实现特殊的方法
抽象类不能直接实例化,只能通过子类进行实例化;普通类可以直接实例化
抽象类允许包含抽象成员方法;普通类中不允许包含抽象方法
抽象类不允许被密封。final密封类不能被继承,防止恶意的派生
属于行为型设计模式
首先定义一个抽象类公开定义总体的算法(算法骨架),但是有些总体算法中需要使用的方法没有办法实现,所以可以延迟到子类中提供
抽象父类:提供算法骨架,并定义抽象方法
public abstract class Bubb1esorter{ //在父类中定义算法实现,没有办法定义的比较方法延迟到子类中提供 public final void sort(object[] arr){ for(int i=1;i<arr.length;i++){ for(int k=0 ; k<arr.length-i ; k++){ //如何实现两个对象的比较 if(bigger(arr[k],arr[k+1])){ object tmp=arr[k]; arr[k]=arr[k+1]; arr[k+1]=tmp; } } } } //由于在父类中没有办法确定如何比较,所以定义抽象方法,要求子类必须提供实现 protected abstract boolean bigger(object obj1,object obj2); }
具体的子类中提供具体的比较方法
public class Pig{//比较并排序的对象 private double weight; }
针对Pig定义对应的排序器
public class Pigsorter extends Bubblesorter{ protected boo1ean bigger(object obj1,object obj2){ if(obj1!=null && obj1 instanceof Pig){ Pig p1=(Pig)obj1; if(obj2 !=null && obj2 instanceof Pig){ Pig p2=(Pig)obj2; return p1.getWeight()>p2.getWeight(); } } return false; } }
何时使用:有一些通用的方法
如何解决:将这些通用算法抽象出来。
封装不变部分,扩展可变部分。
提取公共代码,便于维护。
行为由父类控制,子类实现。
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
OOP要求类内高内聚,类间弱耦合—客户需求变动
public class 农场{ private 冒泡排序器 sorter; //农场类和抽象类耦合的,但是不耦合具体的实现类,所以可以在多个实现类之间进行切换 }