国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

接口

xiyang / 980人閱讀

摘要:恰當的原則是優先選擇類而不是接口。接口是一種重要的工具,但是它們容易被濫用。

接口和內部類為我們提供了一種將接口與實現分離的更加結構化的方法

抽象類和抽象方法

抽象類可以理解為是一種不夠純粹的接口,它是普通類與接口之間的一種中庸之道。

再論初始化

首先看看下面的實例代碼:


class Glyph { void draw() { print("Glyph.draw()"); } Glyph() { print("Glyph() before draw()"); draw(); print("Glyph() after draw()"); } } class RoundGlyph extends Glyph { private int radius = 1; RoundGlyph(int r) { radius = r; print("RoundGlyph.RoundGlyph(), radius = " + radius); } void draw() { print("RoundGlyph.draw(), radius = " + radius); } } public class PolyConstructors { public static void main(String[] args) { new RoundGlyph(5); } } /* Output: Glyph() before draw() RoundGlyph.draw(), radius = 0 Glyph() after draw() RoundGlyph.RoundGlyph(), radius = 5 *///:~

根據Thinking in Java的描述:
1)在其它任何事物發生之前,將分配給對象的存儲空間初始化為成二進制的零(基本類型按照其類型初始化,引用類型為null)
2)調用基類的構造器(如果基類中實例屬性或者靜態屬性有初始化過程則先執行初始化過程),此時,調用被覆蓋后的draw(),由于步驟1的緣故,
我們會發現radius的值為0.
3)按照聲明的順序調用成員的初始化方法
4)調用導出類的構造器主體
之所以出現上面的這種問題,是因為初始化的順序,以及在構造器中調用了可以被子類重寫的方法造成的。這種錯誤往往難以發現。如何避免這種
錯誤呢?在編寫構造器時有一個重要的準則:“用盡可能簡單的方法使對象進入正常狀態:如果可以的話,避免調用其他方法”
在構造器中唯一能夠安全調用的那些方法是基類中的final方法()(也適用于private方法,因為private方法自動屬于final方法),

接口為Java提供了多重繼承

使用接口的核心原因:
為了能夠向上轉型為多個基類型(以及由此帶來的靈活性).看看下面的示例代碼:


package c07.po; interface CanFight { void fight(); } interface CanClimb { void canClimb(); } interface CanSwim { void swim(); } interface CanFly { void fly(); } class ActionCharacter { public void fight() { } } class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly,CanClimb { @Override public void fly() { } @Override public void swim() { } @Override public void canClimb() { } } public class Adventure { public static void t(CanFight x) { x.fight(); } public static void u(CanSwim x) { x.swim(); } public static void v(CanFly x) { x.fly(); } public static void w(ActionCharacter x) { x.fight(); } public static void c(CanClimb c) { c.canClimb(); } public static void main(String[] args) { Hero h = new Hero(); t(h); // Treat it as a CanFight u(h); // Treat it as a CanSwim v(h); // Treat it as a CanFly w(h); // Treat it as an ActionCharacter c(h); // Treat it as a CanClimb } }

接口帶給Java多重繼承的特性,可以使一個對象C既可以被認作是A對象,也可以被認作是B對象,并且在被認作是A或者B對象的時候可以利用多態實
現不同對象的同一方法的不同的行為。這樣就提高了設計的靈活性。并且在對象C作為方法參數時,最好使用它的基類型作為參數類型,這樣對象c即
適用于以類型A作為參數類型的方法,也可以適用于類型B作為參數類型的方法,提高了靈活性。
可以這么說:接口是保證系統可擴展可插拔的基礎(關鍵因素),一個設計良好的系統必須留有足夠的接口。

接口是允許多繼承的

通過繼承,可以很容易的在接口中添加新的方法聲明,還可以通過繼承在新接口中組合數個接口。這兩種情況都可以獲得新的接口,可以參看下面的
示例代碼:

package c07.po;

interface Monster {
    void menace();
}

interface DangerousMonster extends Monster {
    void destroy();
}

interface Lethal {
    void kill();
}

class DragonZilla implements DangerousMonster {
    public void menace() {
    }

    public void destroy() {
    }
}

interface Vampire extends DangerousMonster, Lethal {
    void drinkBlood();
}

class VeryBadVampire implements Vampire {
    public void menace() {
    }

    public void destroy() {
    }

    public void kill() {
    }

    public void drinkBlood() {
    }
}

public class HorrorShow {
    static void u(Monster b) {
        b.menace();
    }

    static void v(DangerousMonster d) {
        d.menace();
        d.destroy();
    }

    static void w(Lethal l) {
        l.kill();
    }

    public static void main(String[] args) {
        DangerousMonster barney = new DragonZilla();
        u(barney);
        v(barney);
        Vampire vlad = new VeryBadVampire();
        u(vlad);
        v(vlad);
        w(vlad);
    }
} // /:~


組合接口時的命名沖突

實現多重繼承時,可能會遇到一個小麻煩。兩個接口的包含方法簽名和返回類型都完全一致的方法當然沒有什么問題,但是下面的例子就有些麻煩了
先考慮一件事情:編譯器是無法分別一個方法名和方法參數都相同僅有返回值不同的方法的。兩個方法簽名完全一致的方法會導致編譯器報錯。
關于方法簽名可以這么簡單的理解:方法的名字,方法的參數列表(包括參數類型和參數的順序)組成方法的方法簽名。
看看下面的示例代碼:


public interface F1 { void f(); String g(); } public interface F2 { void f(int i ); int g(int g); } public interface F3 { int f(); } public class F1F2 implements F1, F2 { /** * 接口F1的方法void f() 與接口F2的方法void f(int i ) 名稱相同但是參數列表不同,所以可以形成重載overload * 這是可行的,也就是不同接口兩個方法同名但是參數列表不同 */ @Override public void f(int i) { } @Override public void f() { } /** * 接口F1的String g()和接口F2的int g(int g)只有方法名稱相同,參數和返回值都不同,不形成重載 */ @Override public int g(int g) { return 0; } @Override public String g() { return null; } } public class F1F3 implements F1,F3 {//The type F1F3 must implement the inherited abstract method F3.f() /**ERROR * The return type is incompatible with F3.f() 接口F1的void f()方法與接口F3的方法int f()參數列表和名稱完全相同,只有返回值不同,不能形成重載,但是也無法通過 編譯,編譯器無法分別兩個同名同參的方法 所以類F1F3是無法同時兼容接口F1和F3的 當然這種蛋疼的事情還是很少遇見的。 @Override public void f() { // TODO Auto-generated method stub } */ @Override public String g() { return null; } }
方法簽名

摘抄自一段提問
What is method signature in java?

The term "method signature" has an exact meaning in Java and is explicitly defined in the Java Language Specification.
The signature of a method consists of the method name and the parameter list (type and number). It DOES NOT include the return type or modifiers such as access modifiers (public, protected, , private), abstract, static, etc.

For example, you cannot have two methods with the same name and parameter list that differs only in that one is static and the other is not, or that differ in that one returns void and the other returns a non-void value.

The use of generics resulted in the addition of the term subsignature, which is documented in the latest Java Language Specification

原文鏈接:https://answers.yahoo.com/question/index?qid=20070306205943AAAsAnx

Java給出的官方文檔的解釋是這樣的:

8.4.2. Method Signature

Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

m2 has the same signature as m1, or

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.

It is a compile-time error to declare two methods with override-equivalent signatures in a class.


class Point { int x, y; abstract void move(int dx, int dy); void move(int dx, int dy) { x += dx; y += dy; } } /** This program causes a compile-time error because it declares two move methods with the same (and hence, override-equivalent) signature. This is an error even though one of the declarations is abstract. **/

The notion of subsignature is designed to express a relationship between two methods whose signatures are not identical, but in which one may override the other. Specifically, it allows a method whose signature does not use generic types to override any generified version of that method. This is important so that library designers may freely generify methods independently of clients that define subclasses or subinterfaces of the library.

class CollectionConverter {
    List toList(Collection c) {...}
}
class Overrider extends CollectionConverter {
    List toList(Collection c) {...}
}

/**
Now, assume this code was written before the introduction of generics, and now the author of class CollectionConverter decides to generify the code, thus:
**/

class CollectionConverter {
     List toList(Collection c) {...}
}

/**
Without special dispensation, Overrider.toList would no longer override CollectionConverter.toList. Instead, the code would be illegal. This would significantly inhibit the use of generics, since library writers would hesitate to migrate existing code.
**/
接口中的域

放入接口中的任何域都都自動是static 和final的,所以接口是一種便捷的用來創建常量的工具。在JavaSE5之前,這是產生enum類型的唯一途徑
接口中的域不可以是“空final的”,但是可以被非常量表達式初始化。
接口的靜態常量的初始化只有在接口加載的時候才會進行初始化,比如直接調用接口常量可以引起接口常量的初始化,再比如子類調用實現接口的方法
會引起接口常量的初始化.實例代碼如下:


public class Value { private String str; public Value(String str){ this.str = str; System.out.println(this.str); } } public interface InterFaceA { public Value v1 = new Value("v1"); Value v2 = new Value("v2"); void printValue(); } public class TC { public static Value v1TC = new Value("v1TC"); public static Value v2TC= new Value("v2TC"); } public class ImplA extends TC implements InterFaceA{ public ImplA(){ System.out.println("ImplA構造函數來啦"); } @Override public void printValue() { System.out.println(v1); System.out.println(v2); } } package c07.ta; import static org.junit.Assert.*; import org.junit.Test; public class TestClient { /** * 直接訪問接口常量,會引起接口常量的初始化(全部常量) */ @Test public void test1() throws Exception { Value v1 = ImplA.v1; //輸出 : v1 v2 } /** * 只初始化接口子類,只會先初始化父類的靜態常量,再初始化子類 * 并不會進行接口的初始化,也不會有接口靜態常量的初始化 */ @Test public void test2() throws Exception { ImplA implA = new ImplA(); /*輸出: * v1TC v2TC ImplA構造函數來啦 */ } /** *初始化接口子類,并且調用子類實現接口的方法,會引起接口的初始化,那么接口的靜態常量也就初始化了 */ @Test public void test3() throws Exception { ImplA implA = new ImplA(); implA.printValue(); /*輸出: v1TC v2TC ImplA構造函數來啦 v1 v2 c07.ta.Value@18fe7c3 c07.ta.Value@b8df17 */ } }
不要總是使用接口進行設計

“確定接口是理想的選擇,因而應該總是選擇接口而不是具體的類”這其實是一種誘惑。這種邏輯看起來是這樣的:因為需要使用不同的具體實現,因此總應該添加這種抽象性
。這句話本身并沒有錯,但是卻成為草率設計濫用接口的指導。
首先需要明確的一點是:任何抽象性都應該是由真正的需求而產生的。當必須時,你應該重構接口而不是到處添加額外級別的間接性,并由此帶來額外的復雜性。
如果過度的對接口抽象,那么帶來的后果則是類膨脹和復雜性的增加,因此既要保證系統的靈活性和可擴展性(利用多態特性,實現接口進行抽象),也要保證系統的復雜性不過分提高(慎用接口)。
恰當的原則是優先選擇類而不是接口。從類開始,如果接口的必須性變得非常明確,那么就進行重構。接口是一種重要的工具,但是它們容易被濫用。
所以我認為合適的設計過程應該是先從劃分類開始,先劃分類的功能,再對類進行重新審視和設計,對類進行重構并且提煉出抽象類,在這基礎上再進行接口的抽象,接口抽象后再進行審視,對接口進行重構,之后再審視接口與類,這樣完成從底到上,在從頂到下的設計一個系統(子系統,模塊,三五個類組成的組件)。

author zhaob
time : 2014-09-14 16:57

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64137.html

相關文章

  • 持續更新免費的API,做一個API的搬運工

    摘要:為了方便廣大的開發者,特此統計了網上諸多的免費,為您收集免費的接口服務,做一個的搬運工,以后會每月定時更新新的接口。將長段中文切詞分開。 為了方便廣大的開發者,特此統計了網上諸多的免費API,為您收集免費的接口服務,做一個api的搬運工,以后會每月定時更新新的接口。有些接口來自第三方,在第三方注冊就可以成為他們的會員,免費使用他們的部分接口。 百度AccessToken:針對HTTP ...

    Shihira 評論0 收藏0
  • 不用寫代碼,也能做好接口測試

    摘要:接口測試形式單個接口測試包含性能測試和通過接口調用進行場景測試。充分來說就是接口測試相對容易實現自動化持續集成。 本文你將了解到 1、接口測試基本概念,包含什么是接口,什么是接口測試,為什么要做接口測試2、接口測試用例設計3、怎樣不用寫代碼,也能快速的根據開發的API文檔完成接口自動化測試腳本 注:如果你對接口基本概念和接口測試用例已熟悉,可以直接跳過,其實看一遍也無防,就當作 溫故知...

    idisfkj 評論0 收藏0
  • 12.java 接口

    摘要:接口的對象可以利用子類對象的向上轉型進行實例化賦值。接口文件保存在結尾的文件中,文件名使用接口名。接口相應的字節碼文件必須在與包名稱相匹配的目錄結構中。接口不能包含成員變量,除了全局常量定義。 概念 接口,在JAVA編程語言中是一個引用類型,是抽象方法的集合,接口通常以interface來聲明。一個類通過繼承接口的方式,從而來繼承接口的抽象方法。 接口中只能包含抽象方法和全局常量。 接...

    pinecone 評論0 收藏0
  • Java 接口(9)

    摘要:接口和內部類為我們提供了一種將接口與實現分離的更加結構化的方法。 接口和內部類為我們提供了一種將接口與實現分離的更加結構化的方法。 1.抽象類和抽象方法 抽象類,是普通的類與接口之間的一種中庸之道. 抽象方法:僅有聲明而沒有方法體. 抽象類:包含抽象方法的類.如果一個類包含一個或多個抽象方法,該類必須被限定為抽象的. 如果從一個抽象類繼承,并想創建該新類的對象,那么久必須為基類中的所...

    lncwwn 評論0 收藏0
  • Java 接口與抽象類方式實現類的擴展

    摘要:子類繼承抽象類,并具體實現方法。抽象類的使用區別于具體類,抽象類無法直接創建抽象類對象,但是可以聲明抽象類的變量,引用抽象類對應具體子類對象。接口優于抽象類中討論到一條規則接口優于抽象類。接口聲明能力,抽象類提供默認實現全部或部分方法。 接口 類,強調數據類型(自定義)的概念,在一些情況下,并不能反映對象以及對象操作的本質。有時我們關注的并非對象的類型,而是對象的能力。 接口聲明一組功...

    neroneroffy 評論0 收藏0
  • 面向對象基本原則(1)- 單一職責原則與接口隔離原則

    摘要:面向對象基本原則單一職責原則與接口隔離原則面向對象基本原則單一職責原則與接口隔離原則面向對象基本原則里式代換原則與依賴倒置原則面向對象基本原則最少知道原則與開閉原則一單一職責原則單一職責原則簡介單一職責原則的英文名稱是,簡稱。 面向對象基本原則(1)- 單一職責原則與接口隔離原則 面向對象基本原則(1)- 單一職責原則與接口隔離原則面向對象基本原則(2)- 里式代換原則與依賴倒置原則面...

    lunaticf 評論0 收藏0

發表評論

0條評論

xiyang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<