java 介面學習

来源:http://www.cnblogs.com/roucheng/archive/2016/04/29/javajiekou.html
-Advertisement-
Play Games

你應該知道介面是一種契約,它與實現方式無關 但是類,即使是抽象類,你都能自定義成員變數,而成員變數往往就與實現方式有關。 這一點的實際意義不大。 但是有一點,類會暴露太多不必要,甚至不能暴露的東西,你看一下java.util中,大部分的數據結構,都被設計成了介面-抽象類-最後實際類 例如Collec ...


你應該知道介面是一種契約,它與實現方式無關

但是類,即使是抽象類,你都能自定義成員變數,而成員變數往往就與實現方式有關。

這一點的實際意義不大。

但是有一點,類會暴露太多不必要,甚至不能暴露的東西,你看一下java.util中,大部分的數據結構,都被設計成了介面-抽象類-最後實際類

例如Collection-List
L-AbstractCollection
L-AbstractList
L-ArrayList

但是有一個,由於歷史原因,被設計成了類,比如Stack extends Vector,
你應該知道Stack的數據訪問模式,就只能是LIFO,但是Vector是一個List,可以隨機訪問,可以任意增減。

結果Stack s = new Stack();

不光能夠pop/push/peer還能add,get,set,remove

如果你用一個介面IStack 裡面只有pop/push/peer方法,然後仍然通過繼承Vector的方式實現,

IStack s = new MyStack();

此時,就無法add,get,set,remove

舉個生動一點的例子

public interface BritishSpy {
public String speak(); //英國間諜講英語
}

public interface GermanSpy {
public String sprechen(); //德國間諜講德語
}

public class DoubleAgent implements BritishSpy, GermanSpy {
public String speak() { return "Hello"; }
public String sprechen() { return "Gutentag"; }
}
// hovertree.com
public class Agency {
public static void toMI5(BritishSpy spy) {
//軍情5處當然只能說英語,做英國間諜
spy.speak();
//spy.sprechen();不可見
}

public static void inGermany(GermanSpy spy) {
//spy.speak();不可見
spy.sprechen();
}

public static void main(String[] args) {
DoubleAgent da = new DoubleAgent();
BritishSpy es = (BritishSpy) da;
GermanSpy gs = (GermanSpy) da;
toMI5(da); //MI5也不知道他是一個雙重間諜,只知道他是BritishSpy
toMI5(es); //更安全  何問起
//toMI5(gs); 不可能
inGermany(da); //在德國還是安全的,德國人不知道他的雙重間諜身份,只知道他是GermanSpy
inGermany(gs); 
//inGermany(es); 不可能
}
}

 

假設你只用class,因為不能多重繼承,所以,speak()/sprechen()比然聲明在同一個class裡面


public abstract class DoubleAgent extends Spy/**(略...)*/ {
public abstract String speak();
public abstract String sprechen();
}

public class PoorDoubleAgent {
public String speak() { return "Hello"; }
public String sprechen() { return "Gutentag"; }
}

晚了,不管你PoorDoubleAgent a = new PoorDoubleAgent();還是DoubleAgent a = new PoorDoubleAgent();,全世界都知道他是一個雙重間諜,他到哪裡都必死無疑
前面舉了一個關於“安全性”方面的例子

介面只暴露給對方(比如Agent的軍情5處方法)它所需要的足夠信息,其他無關的,甚至有害的信息不會暴露給對方。因為,我傳給你的是介面類型,我除了是這個介面(和這個介面的父介面,inteface A extends B, C)的實例外,你頂多知道我是一個Object(不是int:P),其他的姓甚名誰,哪裡住址,父母安好,兄妹幾何都與你無關,我們只需要關心我們簽訂的合同(介面) 

再舉一個有關靈活性方面的例子

假設某公司已經有一個更新過N代的,邏輯複雜無比
public class A extends B /** where b extends c, c extends d and so on... */ {
public void init() {...}
public void release() {...}
public String doXXX() {...}
public String doYYY() {...}
}

而這個A又被很多類繼承或使用,doXXX/doYYY 方法已經無法更改

假設現在這個公司要參加某個標準化組織,而這個組織要求所有提供這樣的方法

String getXXX(); String getYYY();

加入用介面標準化組織只要規定成員們都實現
public interface IBusiness {
String getXXX();
String getYYY();
}
而這個公司只需要稍微改寫一點點即可
public class A extends B /** where b extends c, c extends d and so on... */
implements IBusiness {
public String getXXX() { return doXXX(); }
public String getYYY() { return doYYY(); }

//保留
public void init() {...}
public void release() {...}
public String doXXX() {...}
public String doYYY() {...}
}

這樣既滿足了標準化的要求,又滿足了無需修改原來繼承A或者使用A的無數個class(有些可能在用戶那裡,不可能更改)

假如不用介面,你有兩個選擇:數典忘祖或者自絕於人

數典忘祖:
你的新A必須繼承標準化組織的Business,原來a,b, c d...裡面的代碼全部得重新組織到這個新的A裡面,與此同時,那些調用或者繼承A的class難保不需要重寫

自絕於人
原來的就讓它去,誰也別再提它了,我們以後就用新的NewA,結果,你的新客戶倒是滿足了標準化,你的老客戶可就 :< :@ :$,而且以後需要維護A和NewA
定義介面:
interface Fight{
void fight();
}

肥肥和瘦瘦去實現這個介面:
class FatFat implements Fight{
public void fight(){
System.out.println("FatFat 打人很痛!");
}
}

class ThinThin implements Fight{
public void fight(){
System.out.println("ThinThin 打人一點都不痛!!哈哈。");
}
}

然後你可能會這另一個類中使用到FatFat和ThinThin的對象,然後都去執行fight,但是你可能不到運行時就不會知道是具體的那個類的對象,這是你就感謝他們都實現了Fight介面,你可以向上轉型,然後通過運行時的多態產生你想要的行為。http://hovertree.com/menu/java/

Fight a=new FatFat();
Fight b=new ThinThin();
a.fight();
b.fight();
這樣就會執行不同的動作。

或者如果你有一個方法
f(Fight i){
i.fight();
}

如果c是實現了Fight介面的其中一個類,那麼你就可以這樣使用這個方法:
f(c);
你不需要知道c究竟是什麼對象(不管是FatFat還是ThinThin),你都可以得到你想要的fight動作

轉自:http://hovertree.com/h/bjaf/0c6sbcn8.htm

推薦:http://www.cnblogs.com/roucheng/p/3504465.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一般我們寫好實體之後,配置好數據上下文對象,還有在配置文件中改好連接字元串之後。 還不能生成資料庫,自動生成資料庫,有兩步關鍵步驟: 1. Enable Migrations 2. Update-database 執行玩第二步之後,就自動生成了資料庫。 實例 //實體: using System; ...
  • [re: Orchard CMS] This caused me scratching my head for days and now I can even feel it's bleeding. The answer however is the simplest. Because it's n ...
  • MVC中有一個處理異常的過濾器 HandleErrorAttribute 1.新建一個類繼承自 HandleErrorAttribute,然後重寫OnException這個方法 只要程式出錯就會執行這個方法。 2.註冊定義好的異常過慮器 打開App_Start文件夾中FilterConfig.cs修 ...
  • 最近在做一個項目時,客戶要求網站能夠集成QQ登錄的功能,以前沒做過這方面的開發,於是去QQ的開放平臺官網研究了一下相關資料,經過自己的艱苦探索,終於實現了集成QQ登錄的功能,現在把相關的開發經驗總結一下,希望對有這方面需求的朋友有所幫助。 一.前期準備 首先你需要登錄QQ的開發平臺註冊一個賬號,QQ ...
  • 1、Enable-Migrations 啟用遷移 2、Add-Migration 為掛起的Model更改創建遷移版本 2、Update-Database 更新資料庫命令 (1)預設更新到最新版本 (2)更新到特定版本 -TargetMigration(如下圖)。 此命令可當作回滾用,如我已經完成了所 ...
  • 獲取【下載地址】 【免費支持更新】三大資料庫 mysql oracle sqlsever 更專業、更強悍、適合不同用戶群體【新錄針對本系統的視頻教程,手把手教開發一個模塊,快速掌握本系統】 A集成代碼生成器 [正反雙向(單表、主表、明細表、樹形表,開發利器)+快速構建表單;freemaker模版技術 ...
  • 步驟一:在聲明的數據域中按Ctrl+1: 步驟二:點擊最後一個選項Create getter and setter,在彈出的對話框中點擊確定: 在介紹另外一個方法: 步驟一:聲明完類的數據域之後,輸入set,按住Alt+/: 步驟二:同步驟一,輸入get,再按住Alt+/: ...
  • 1.在C++ 程式中調用被C 編譯器編譯後的函數,為什麼要加extern “C”?答:首先,extern是C/C++語言中表明函數和全局變數作用範圍的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變數可以在本模塊或其它模塊中使用。通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變數以關鍵字e ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...