2012-01-02 47 views
4

我其實讀一本書在Java設計模式,我是一個新手:)投到一個抽象類......這怎麼可能?

http://www.amazon.com/Design-Patterns-Java-TM-Software/dp/0321333020/約組成圖案的章節我碰到那個讓我爲難,強制轉換爲一個抽象類代碼,我也有不太清楚當子類調用抽象超類的構造函數時會發生什麼,請你幫助我!

,我說的是在isTree(設置訪問)

 MachineComponent c = (MachineComponent) i.next(); 
     if (visited.contains(c) || !c.isTree(visited)) 

我們如何可以調用子類的isTree方法的石膏,之後他的抽象超 而isTree超類方法是投抽象?

這裏有兩類片段:

package com.oozinoz.machine; 
/* 
* Copyright (c) 2001, 2005. Steven J. Metsker. 
*/ 

import java.util.*; 
import com.oozinoz.iterator.ComponentIterator; 

/** 
* Objects of this class represent either individual machines or composites of 
* machines. 
*/ 

public abstract class MachineComponent { 

    /* 
    * Subclasses implement this to support the isTree() algorithm. 
    */ 

    protected abstract boolean isTree(Set s); 

    // rest of class omitted 
} 

2:

package com.oozinoz.machine;  
/* 
* Copyright (c) 2001, 2005. Steven J. Metsker. 
*/ 

import java.util.*; 
import com.oozinoz.iterator.ComponentIterator; 
import com.oozinoz.iterator.CompositeIterator; 

/** 
* Represent a collection of machines: a manufacturing line, a bay, or a 
* factory. 
*/ 

public class MachineComposite extends MachineComponent { 
    protected List components = new ArrayList(); 

    /** 
    * @param visited a set of visited nodes 
    * @return true if this composite is a tree 
    * @see MachineComponent#isTree() 
    */ 

    protected boolean isTree(Set visited) { 
     visited.add(this); 
     Iterator i = components.iterator(); 
     while (i.hasNext()) { 
      MachineComponent c = (MachineComponent) i.next(); 
      if (visited.contains(c) || !c.isTree(visited)) 
       return false; 
     } 
     return true; 
    } 

    // rest of class omitted 
} 
+1

請正確格式化你的代碼,如果你打算只轉儲在整個文件 – 2012-01-02 00:26:14

回答

8

這是運行時類型(實際類型)和編譯時類型之間的區別。

對抽象類MachineComponent的類型轉換很好,因爲實際的對象實例實際上是一些非抽象的子類MachineComponent,它實現了所有的抽象方法。

摘要MachineComponent類是分配變量的編譯時類型。但是沒有實際的實例是(或可以)用這個抽象類創建的。

+2

@ wrscheider99 - 絕對正確。事實上,這就是抽象類的定義 - 它是一個你不能創建任何具體實例的類 - 你必須在ORDER中創建一個具體實例。坦率地說,「接口」在Java中往往是非常有用的。但是抽象類*在很多情況下很重要,包括OP的例子。 – paulsm4 2012-01-02 01:59:09

1

問:你能否轉換爲抽象類?

答:當然 - 你當然可以。

不能 do是調用抽象類的抽象方法。 (從評論部分插入--Andrew Barber-下面) - 你實際上是在子類中調用它的具體實現。

+6

呀......完全不對。 – mre 2012-01-02 00:08:47

+2

@mre,這是不是真的?一個抽象方法沒有代碼,所以你會打電話給什麼? – Paul 2012-01-02 02:01:34

+1

這是真的,雖然我可以看到有些人可能不會這麼認爲,如果他們挑選的條款不同於回答者。如果你認爲你在調用抽象函數,你實際上是在子類中調用它的具體實現。 – 2012-01-02 02:08:11

2

那麼,讓我們以Cat這是抽象類Animal的子類。因爲貓是動物。它具有一般動物所做的一切,因爲它具有動物的功能。

子類化抽象類是相同的。你可以簡單地使用「是」,因爲它是一個子類。

您可以將動物列表定義爲動物園,但它可以有狗和貓 - 畢竟,它們都是動物。

鑄造一個CatAnimal實際上並沒有使它少了Cat比它的是 - 你只要告訴你的代碼,把它像它像對待任何其他動物。

編輯
如果你不喜歡貓(我也不)讓我將你重定向到Wikipedia article about inheritance。如果你不能施放它們,抽象類將無用武之地。

4

isTree只是抽象類的抽象類。一旦該類被初始化爲非抽象類,將其轉換爲抽象類將不會改變其內存。因此,調用抽象類上的方法有效地將其稱爲具體實現。

它有用的原因是通過抽象實現傳遞子類。

假設一個String類有'length'方法。沒有必要爲每個可能的String類型的子類都有一個函數。相反,您轉換爲具有「長度」實現的基本(抽象)字符串,並將其傳遞。

3

OK - 讓我們再試一次:

問:你可以同時投射到一個抽象類?

答:當然 - 當然你也可以

例如:

public class UseAbstract 
{ 
    public static void main (String[] args) 
    { 
    // Instantiate an abstract class 
    AbstractPet myDog = new Dog(); 
    myDog.sound(); 

    // Instantiate a concrete class 
    Cat myCat = new Cat(); 
    myCat.sound(); 

    // Cast a concrete class to an abstract class 
    AbstractPet somePet = (AbstractPet)myCat; 
    somePet.sound(); 
    } 
} 

abstract class AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("eek"); 
    } 
} 

class Dog extends AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("Woof"); 
    } 
} 

class Cat extends AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("meow"); 
    } 
}