簡體   English   中英

Java接口和類型

[英]Java interfaces and types

假設您有一些Java代碼,如下所示:

 public class Base{
    public void m(int x){
    // code
    }
 }

然后是派生的子類,該子類將Base擴展如下:

 public class Derived extends Base{
    public void m(int x){ //this is overriding
      // code
    }

    public void m(double x){ //this is overloading
      // code
    }
 }

然后您有一些聲明如下:

Base b = new Base();
Base d = new Derived();
Derived e = new Derived();

b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works

對於不編譯的人,我知道您正在將Double傳遞給Base的m方法版本,但是我不明白的是……曾經有一個類似“ Base b = new”的聲明有什么意義? Derived();“

這似乎是遇到各種類型轉換問題的好方法,並且,如果您要使用派生對象,為什么不去像“ e”這樣的聲明呢?

另外,對於Java中使用的“類型”一詞的含義,我有些困惑。 我今年夏天早些時候學到的方法是, 每個對象都有一個類該類對應於實例化一個對象時“ new”之后的類的名稱,但是一個對象可以具有任意多個類型 例如,“ e”的類型為Base,Derived(和Object;)),但其類為Derived。 這個對嗎?

另外,如果Derived實現了一個名為CanDoMath的接口(同時仍在擴展Base),那么說它具有類型“ CanDoMath”以及Base,Derived和Object是否正確?

我經常以以下形式編寫函數:

public Collection<MyObject> foo()  {}  

public void bar(Collection<MyObject> stuff){}

在兩個實例中我都可以很容易地將其設置為ArrayList ,但是如果以后我決定將表示形式SetSet ,會發生什么情況? 答案是自從我改變方法合同以來,我有很多重構工作。 但是,如果我將其保留為Collection ,則可以隨意將其從ArrayList無縫更改為HashSet 使用ArrayList的示例,它具有以下類型:

 Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess

在許多情況下,不希望將自己限制在特定的(子)類上,例如em(8.0); 例如,假設您有一個名為move的方法,該方法可在程序的坐標圖中移動對象。 但是,在編寫方法時,可能同時具有由不同類處理的笛卡爾圖和徑向圖。

如果您依靠了解子類是什么,則會迫使自己處於一種位置,在這種情況下,較高級別的代碼必須了解較低級別的代碼,而實際上,他們只是想依靠存在具有特定簽名的特定方法這一事實。 有很多很好的例子:

  • 想要在不知道如何建立連接的同時將查詢應用於數據庫。
  • 想要對用戶進行身份驗證,而不必提前知道所使用的策略。
  • 希望對信息進行加密,而無需采用更好的加密技術就可以刪除大量代碼。

在這些情況下,您只需要確保對象具有特定的類型,就可以保證特定的方法簽名可用。 這樣,您的示例就是人為的。 您是在問為什么不只使用具有方法的類(而不是不可用的類),該方法的特征是將double用作簽名的參數。 (簡單地說;您不能使用沒有可用方法的類。)

還有另一個原因。 考慮:

class Base {
   public void Blah() {
     //code
   }
}

class Extended extends Base {
   private int SuperSensitiveVariable;

   public setSuperSensistiveVariable(int value) {
     this.SuperSensistiveVariable = value;
   }

   public void Blah() {
     //code
   }
}

//elsewhere
Base b = new Extended();
Extended e = new Extended();

請注意,在b情況下,我無權訪問set()方法,因此不會意外地將超靈敏變量弄亂。 我只能在e情況下這樣做。 這有助於確保僅在正確的位置完成這些操作。

您對類型的定義是好的,對特定對象將具有什么類型的理解也是如此。

Base b = new Derived();

這樣做的目的是使用多態來更改您的實現。 例如,某人可能會這樣做:

List<String> strings = new LinkedList<String>();

如果他們進行了一些分析,發現此列表上最常見的操作對於列表類型而言效率低下,則可以將其換出為ArrayList。 通過這種方式,您可以獲得靈活性。

如果要使用派生對象

如果需要派生對象上的方法,則可以使用派生對象。 看一下BufferedInputStream類-您之所以使用它,不是因為其內部實現,而是因為它包裝了InputStream並提供了便利的方法。

另外,對於Java中使用的“類型”一詞的含義,我有些困惑。

聽起來您的老師將接口和類稱為“類型”。 這是一個合理的抽象,因為實現接口並擴展該類的類可以通過3種方式引用,即

public class Foo extends AbstractFoo implements Comparable<Foo>

// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();

在不同上下文中使用的類型的示例:

new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection

這是面向對象設計的經典問題之一。 當發生這種情況時,通常意味着可以改進設計。 對於這些問題,幾乎總是有一種優雅的解決方案。

例如,為什么不將需要加倍的m拖入基類?

關於第二個問題,一個對象可以具有多個類型,因為接口也是類型,並且類可以實現多個接口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM