abstract class A { public abstract void fun(); }; class B extends A { public void fun() { System.out.println("B ==> Hello World"); } }; class C extends A { public void fun() { System.out.println("C ==> Hello World"); } }; public class Demo01 { public static void main(String args[]) { A a = new C(); a.fun(); } };
抽象類是可以實例化的,通過對象的多態(tài)性來實例化抽象類的主要作用是什么呢?抽象類就是類似于一個模板操作 ==>java WEB Servlet程序,提供的就是一個模板。
把上面的實際的例子變?yōu)槌绦騛bstract class Err { public void printInfo() { System.out.println("姓名:"+this.getName()); System.out.println("班級:"+this.getCls()); System.out.println("事由:"+this.getCau()); } //得到姓名,由具體的子類去做 public abstract String getName(); //得到班級,由具體的子類去做 public abstract String getCls(); //得到事由 public abstract String getCau(); } class ZhangSan extends Err { public String getName() { return "張三"; } public String getCls() { return "小五班"; } public String getCau() { return "因為上課吃東西,所以被老師抓住了,所以要填寫違紀卡。 "; } } class LiSi extends Err { public String getName() { return "李四"; } public String getCls() { return "大五班"; } public String getCau() { return "因為上課睡覺,所以被老師抓住了,所以要填寫違紀卡。 "; } } public class Demo02 { public static void main(String args[]) { Err e = new ZhangSan(); e.printInfo(); } }
我們改成李四看看效果哈~abstract class Err { public void printInfo() { System.out.println("姓名:"+this.getName()); System.out.println("班級:"+this.getCls()); System.out.println("事由:"+this.getCau()); } //得到姓名,由具體的子類去做 public abstract String getName(); //得到班級,由具體的子類去做 public abstract String getCls(); //得到事由 public abstract String getCau(); } class ZhangSan extends Err { public String getName() { return "張三"; } public String getCls() { return "小五班"; } public String getCau() { return "因為上課吃東西,所以被老師抓住了,所以要填寫違紀卡。 "; } } class LiSi extends Err { public String getName() { return "李四"; } public String getCls() { return "大五班"; } public String getCau() { return "因為上課睡覺,所以被老師抓住了,所以要填寫違紀卡。 "; } } public class Demo02 { public static void main(String args[]) { Err e = new LiSi(); e.printInfo(); } }調用模板成功了哈~
(模板設計)場景: 假設Person分為Worker和Student,工人的屬性包括:姓名、年齡、工資,學生的屬性包括:姓名、年齡、成績,那么現在人都可以說話,但是工人和學生說的話肯定不一樣。此時,肯定人中的說話方法是固定的,肯定是一個普通方法,只是說話的內容不一樣。abstract class Person { private String name; private int age; public Person(String name,int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public void talk() { //這是要說,內容都在此方法中 System.out.println(this.getContent()); } public abstract String getContent(); } class Student extends Person { private float score; public Student(String name,int age,float score) { super(name,age); this.score = score; } public String getContent() { return "學生說 --> 姓名="+super.getName() +",年齡="+super.getAge() +",成績="+this.score; } } class Worker extends Person { private float salary; public Worker(String name,int age,float salary) { super(name,age); this.salary = salary; } public String getContent() { return "工人說 --> 姓名="+super.getName() +",年齡="+super.getAge() +",工資="+this.salary; } } public class Demo03 { public static void main(String args[]) { Person p1 = new Student("張三",20,90.0f); Person p2 = new Worker("李四",30,900.0f); p1.talk(); p2.talk(); } }
接口的實際應用
分布式代碼中最重要的就是要規(guī)定好操作的接口。接口就是定義了一個標準,只要按照此標準代碼都可以正常使用。interface A { public String getInfo(); } class B implements A { public String getInfo() { return "B --> Hello World"; } } class C implements A { public String getInfo() { return "C --> Hello World"; } } public class Demo04 { public static void main(String args[]) { A a = new B(); System.out.println(a.getInfo()); } }證明接口對象可以實例化,通過對象多態(tài)性進行向上轉型,接口是可以實例化的。
我們改成C看看效果interface A { public String getInfo(); } class B implements A { public String getInfo() { return "B --> Hello World"; } } class C implements A { public String getInfo() { return "C --> Hello World"; } } public class Demo04 { public static void main(String args[]) { A a = new C(); System.out.println(a.getInfo()); } }我們發(fā)現都可以利用對象多態(tài)性完成操作
接口是一個標準。 USB接口 --> 只要是實現了USB接口的設備就都可以向USB接口上插。 舉例: 假設現在設計一個USB接口,里面只有開始工作和停止工作的操作。主板上有USB接口,表示可以插入任意的USB設備。interface USB { //表示開始工作 public void start(); //表示停止工作 public void stop(); } class MainBoard { //只要是USB設備就可以插 public static void plugIn(USB usb) { usb.start(); usb.stop(); } } class MP3 implements USB { public void start() { System.out.println("MP3開始工作"); } public void stop() { System.out.println("MP3停止工作"); } } class Print implements USB { public void start() { System.out.println("打印機開始工作"); } public void stop() { System.out.println("打印機停止工作"); } } public class Demo05 { public static void main(String args[]) { USB u = new MP3(); MainBoard.plugIn(u); } }現在看下效果
如果是打印機呢?interface USB { //表示開始工作 public void start(); //表示停止工作 public void stop(); } class MainBoard { //只要是USB設備就可以插 public static void plugIn(USB usb) { usb.start(); usb.stop(); } } class MP3 implements USB { public void start() { System.out.println("MP3開始工作"); } public void stop() { System.out.println("MP3停止工作"); } } class Print implements USB { public void start() { System.out.println("打印機開始工作"); } public void stop() { System.out.println("打印機停止工作"); } } public class Demo05 { public static void main(String args[]) { USB u = new Print(); MainBoard.plugIn(u); } }
這就是一個典型的操作,一切以接口標準進行操作。接口規(guī)定什么,其就可以完成什么樣的工作哈~舉例: 聽我講課,聽我講課,我說的是中文,你聽的是中文,所以你能聽懂,如果你再說話,你肯定也說中文,我聽的也是中文。接口在實際中可以作為一種標準,那么這種標準在使用的時候就可以讓類之間進行解耦合操作。 接口的重要目的是解耦合: A --> Bclass A { public void fun(B b) { b.print(); } } class B { public void print() { System.out.println("Hello World!!!"); } } public class Demo06 { public static void main(String args[]) { new A().fun(new B()); } }
此代碼存在的問題: 如果現在B類的功能不能直接滿足A類的要求了, 需要對B進行擴充或是把B類徹底替換成另外一個C類,那么此時要完成以下步驟:修改A類、增加C類,那么問有沒有這樣一種可能:修改功能的時候我可以不動類A呢?可以使用接口。class A { public void fun(X x) { x.print(); } } interface X { public void print(); } class B implements X { public void print() { System.out.println("Hello World!!!"); } } class C implements X { public void print() { System.out.println("Hello Java!!!"); } } public class Demo06 { public static void main(String args[]) { X x = new C(); new A().fun(x); } }
問題: 在實際的代碼中main方法實際上應該是作為一個客戶端出現的。 此時客戶端與接口和其接口的子類是直接有關的。代碼中肯定不能這樣編寫,因為會造成客戶端(main)與具體的子類耦合。 JVM的工作原理:*.class -->JVM -->OS :程序可移植性高。class A { public void fun(X x) { x.print(); } } interface X { public void print(); } class B implements X { public void print() { System.out.println("Hello World!!!"); } } class C implements X { public void print() { System.out.println("Hello Java!!!"); } } //中間再加入一個過渡端 class Factory { public static X getInstance(String str) { X x = null; if ("B".equals(str)) { //認為操作的是B類 x = new B(); } if ("C".equals(str)) { x = new C(); } return x; } } public class Demo06 { public static void main(String args[]) { X x = Factory.getInstance("B"); new A().fun(x); } }現在在客戶端就看不到接口了
現在換成C標記class A { public void fun(X x) { x.print(); } } interface X { public void print(); } class B implements X { public void print() { System.out.println("Hello World!!!"); } } class C implements X { public void print() { System.out.println("Hello Java!!!"); } } //中間再加入一個過渡端 class Factory { public static X getInstance(String str) { X x = null; if ("B".equals(str)) { //認為操作的是B類 x = new B(); } if ("C".equals(str)) { x = new C(); } return x; } } public class Demo06 { public static void main(String args[]) { X x = Factory.getInstance("C"); new A().fun(x); } }
此時客戶端并沒有一個具體的子類出現。class A { public void fun(X x) { x.print(); } } interface X { public void print(); } class B implements X { public void print() { System.out.println("Hello World!!!"); } } class C implements X { public void print() { System.out.println("Hello Java!!!"); } } //中間再加入一個過渡端 class Factory { public static X getInstance(String str) { X x = null; if ("B".equals(str)) { //認為操作的是B類 x = new B(); } if ("C".equals(str)) { x = new C(); } return x; } } public class Demo06 { public static void main(String args[]) { if (args.length!=1) { System.out.println("程序參數錯誤,程序無法運行!"); System.exit(1); } X x = Factory.getInstance(args[0]); new A().fun(x); } }
以后如果假設要增加新的子類的時候,只需要修改工廠類即可,其他地方不用做太大的修改,即: 某一個代碼的修改不影響被調用處的代碼就是好的設計。上面的例子中執(zhí)行java Demo06 D出現NullPointerException錯誤,我們可以這樣修改,加個判斷if(x!=null)。class A { public void fun(X x) { if(x!=null) x.print(); } } interface X { public void print(); } class B implements X { public void print() { System.out.println("Hello World!!!"); } } class C implements X { public void print() { System.out.println("Hello Java!!!"); } } //中間再加入一個過渡端 class Factory { public static X getInstance(String str) { X x = null; if ("B".equals(str)) { //認為操作的是B類 x = new B(); } if ("C".equals(str)) { x = new C(); } return x; } } public class Demo06 { public static void main(String args[]) { if (args.length!=1) { System.out.println("程序參數錯誤,程序無法運行!"); System.exit(1); } X x = Factory.getInstance(args[0]); new A().fun(x); } }
最早:接口直接去通過new 子類取得對象,那么這樣造成一個接口與具體的子類直接耦合 現在:接口通過一個工廠類取得子類對象(根據傳入的參數不同),此時接口與具體子類之間沒有直接的耦合關系,所以使用接口可以解耦合。此設計稱為工廠設計模式: 接口 --> 工廠 --> 各個的子類對象總結 1、重點闡述了抽象類和接口的使用 2、注意:自己簡單總結一下抽象類和接口的不同 3、工廠設計新聞熱點
疑難解答