Java基礎之:OOP——抽象類
當父類的某一些方法并不知道具體實作內容,但需要繼承給子類讓其在子類中實作時,就可以將這些方法宣告為抽象方法,而有抽象方法的類就叫做抽象類,使用abstract來宣告,
簡單案例
package com.atguigu.abstract_;
?
public class AbstractTest01 {
?
public static void main(String[] args) {
Cat cat = new Cat("小花貓");
cat.eat();
}
?
}
?
abstract class Animal { //抽象類
private String name;
?
public Animal(String name) {
super();
this.name = name;
}
?
public String getName() {
return name;
}
?
public void setName(String name) {
this.name = name;
}
//eat , 抽象方法
public abstract void eat();
}
?
//解讀
//1. 當一個類繼承了抽象類,就要把抽象類的所有抽象方法實作
//2. 所謂方法實作,指的是 把方法體寫出, 方法體是空,也可以.
class Cat extends Animal {
public Cat(String name) {
super(name);
// TODO Auto-generated constructor stub
}
public void eat() {
System.out.println(getName() + " 愛吃 <?)))><<");
}
}
語法說明
抽象類:
訪問修飾符 abstract class 類名{}
抽象方法:(抽象方法沒有方法體!)
訪問修飾符 abstract 回傳型別 方法名(引數串列);
抽象類使用細節
-
抽象類不可以被實體化
-
抽象類不一定必須包含abstract方法,即抽象類不一定有抽象方法
-
一旦包含了抽象方法,則這個類必須宣告為abstract抽象類
-
abstract只能修飾類與方法,不可以修飾其他內容
-
抽象類可以有任意成員(因為抽象類還是類),比如:非抽象方法、構造器、靜態屬性等等
-
抽象方法不能有主體,即不能實作
-
如果一個類繼承了抽象類,則它必須實作抽象類的所有抽象方法,除非它自己也宣告為abstract類,
-
抽象方法不能使用private、final 和 static來修飾,因為這些關鍵字都是和重寫相違背的,
package class_abstract;
public class Abstract_Test {
?
public static void main(String[] args) {
//細節1:對于抽象類而言,不可以宣告實體
// A a = new A(); //報錯:Cannot instantiate the type A
//細節5.但當抽象類的子類,創建了實體之后,仍然可以使用A類中滿足訪問權限的所有東西,(繼承的特點)
B b = new B();
b.setName("小范");
b.getName();
}
}
?
?
abstract class A{ //細節3:由于A類中的hi()方法是被abstract修飾的(即抽象方法),所以A類也必須宣告為抽象的
private String name; //細節5:抽象類中也可以有非抽象的東西,抽象類本質也是一個類
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
?
public abstract void hi(); //細節6:對于抽象類而言,不可以有{},即方法體
public abstract void hello();
}
?
class B extends A{
//細節7:只要繼承抽象類,則必須實作抽象類中所有的抽象方法,否則編譯器報錯:
//The type B must implement the inherited abstract method A.hi()....
@Override
public void hi() {
System.out.println("B----hi");
}
@Override
public void hello() {
System.out.println("B-----hello");
}
}
?
abstract class C extends A{
/* 細節7:
* 若繼承了抽象類,但子類本身也是一個抽象類,那么可以不用實作抽象類中的抽象方法
* 因為對于抽象子類C而言,是允許抽象方法存在的,
* 一旦有非抽象子類D,繼承了子類C,那么D同樣需要實作抽象子類C中的所有抽象方法
*/
?
// private abstract int age; //abstract 只能修飾方法與類,不可以修飾屬性和其他的
/* 細節8:
* 對于抽象方法而言,不可以使用 private 或 final 修飾
* 因為,抽象的本質就規范化父類的東西,讓子類去實作父類已經寫好的抽象方法
* 而用private與final修飾的方法都不可以被子類繼承,這就與抽象的作用沖突了
*/
// private abstract void m1();
/* 細節8:
* 對于抽象方法而言,也不可以使用 static 修飾
* 因為,static修飾之后,方法不再是成員方法了,而是類方法,
* 而子類是無法繼承類方法的,所以static與abstract的作用也是產生沖突了,
*/
// public static abstract void m2();
}
?
class D extends C{
@Override
public void hi() {
System.out.println("D-----hi");
}
?
@Override
public void hello() {
System.out.println("D-----hello");
}
}
多型在抽象類中的實作
簡單案例
package class_abstract;
?
public class AbstractPolyArray {
?
public static void main(String[] args) {
//抽象類不可以實體化,但可以使用多型陣列
Animal[] animal = new Animal[2];
animal[0] = new Dog("小黑狗");
animal[1] = new Cat("小花貓");
//多型陣列的使用
for (int i = 0; i < animal.length; i++) {
show(animal[i]);
}
}
//這里不用擔心會傳入一個Animal型別的實體,因為Animal不能實體化
//編譯器不會通過,所以只會傳入Animal的子類實體
public static void show(Animal a) {
a.eat(); //多型的使用
if(a instanceof Dog) {
((Dog)a).watch();
}else if(a instanceof Cat) {
((Cat)a).catchMouse();
}
}
}
?
abstract class Animal{
private String name;
?
public Animal(String name) {
super();
this.name = name;
}
?
public String getName() {
return name;
}
?
public void setName(String name) {
this.name = name;
}
//動物都有eat的動作,但我們并不知道每一個動物具體怎么樣eat
//所以這里通過抽象提供了eat方法,需要子類來實作
public abstract void eat();
}
?
class Dog extends Animal{
public Dog(String name) {
super(name);
}
?
@Override
public void eat() {
System.out.println(getName() + "啃骨頭......");
}
public void watch() {
System.out.println(getName() + "守家.....");
}
}
?
class Cat extends Animal{
public Cat(String name) {
super(name);
}
?
@Override
public void eat() {
System.out.println(getName() + "吃魚......");
}
public void catchMouse(){
System.out.println(getName() + "抓老鼠.....");
}
}
程式輸出
小黑狗啃骨頭......
小黑狗守家.....
小花貓吃魚......
小花貓抓老鼠.....
抽象類簡單應用案例
撰寫一個Employee類,宣告為抽象類,包含如下三個屬性:name,id,salary,
-
提供必要的構造器和抽象方法:work(),
-
請使用繼承的思想,設計CommonEmployee類和Manager類,
-
對于Manager類來說,他既是員工,還具有獎金(bonus)的屬性,
-
要求類中提供必要的方法進行屬性訪問,實作work(),提示 "經理/普通員工 名字 作業中...."
package class_abstract;
public class Abstract_ClassWork {
public static void main(String[] args) {
Employee[] em = new Employee[2];
em[0] = new Manager("小黃", 1001, 5000, 1120);
em[1] = new CommonEmployee("小范", 1002, 3000);
System.out.println(em[0].toString());
em[0].work();
System.out.println(em[1].toString());
em[1].work();
}
}
?
abstract class Employee{
private String name;
private int id;
private double salary;
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public abstract void work();
@Override
public String toString() {
return "name=" + name + ", id=" + id + ", salary=" + salary;
}
}
?
//對于Manager類來說,他既是員工,還具有獎金(bonus)的屬性,
class Manager extends Employee{
private double bonus;
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
?
public double getBonus() {
return bonus;
}
?
public void setBonus(double bonus) {
this.bonus = bonus;
}
?
//"經理/普通員工 名字 作業中...."
@Override
public void work() {
System.out.println("經理" + getName() + "作業中......");
}
@Override
public String toString() {
return super.toString() + ",bonus =" + bonus;
}
}
?
class CommonEmployee extends Employee{
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
// TODO Auto-generated constructor stub
}
?
//"經理/普通員工 名字 作業中...."
@Override
public void work() {
System.out.println("普通員工" + getName() + "作業中......");
}
}
程式輸出
name=小黃, id=1001, salary=5000.0,bonus =1120.0
經理小黃作業中......
name=小范, id=1002, salary=3000.0
普通員工小范作業中......
抽象類最佳實踐-模板設計模式
抽象類體現的就是一種模板模式的設計,抽象類作為多個子類的通用模板,子類在抽象類的基礎上進行擴展、改造,但子類總體上會保留抽象類的行為方式,
1) 當功能內部一部分實作是確定,一部分實作是不確定的,這時可以把不確定的部分暴露出去,讓子類去實作,
2) 撰寫一個抽象父類,父類提供了多個子類的通用方法,并把一個或多個方法留給其子類實作,就是一種模板模式
簡單案例
1) 設計一個抽象類(Template),能完成如下功能:
2) 撰寫方法caleTime() ,可以計算某段代碼的耗時時間
3) 撰寫抽象方法code()
4) 撰寫一個子類Sub,繼承抽象類Template,并實作code方法,
package class_abstract; public class Abstract_Template { public static void main(String[] args) { Template sub = new Sub(); sub.caleTimes(); //實際是呼叫了Template中的caleTimes方法 Template subStringB = new SubStringB(); subStringB.caleTimes(); //這里可以看到 StringBuffer在拼接字串時,遠遠優于String拼接的效率 } } ? abstract class Template{ //抽象類 public abstract void code(); //抽象方法 public void caleTimes(){ // 統計耗時多久是確定 //統計當前時間距離 1970-1-1 0:0:0 的時間差,單位ms long start = System.currentTimeMillis(); code(); //這里的code在呼叫時,就是指向子類中已經重寫實作了的code long end = System.currentTimeMillis(); System.out.println("耗時:"+(end-start)); } } ? class Sub extends Template{ @Override public void code() { String x = ""; for(int i = 0;i < 10000 ; i++) { //拼接1W個hello 看處理時間 x += "hello" + i; } } } ? class SubStringB extends Template{ @Override public void code() { StringBuffer stringBuffer = new StringBuffer(); for(int i = 0;i < 10000 ; i++) { //拼接1W個hello 看處理時間 stringBuffer.append("hello" + i); } } }
?
程式輸出
耗時:606
耗時:2
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/235249.html
標籤:其他
