2010-05-16 84 views
10

有兩個具有相同簽名的構造函數的用例是什麼?爲什麼你會有兩個具有相同簽名的構造函數?

編輯:你不能在Java中這樣做,因爲Effective Java說你需要靜態工廠。但我想知道爲什麼你首先需要這樣做。

+1

恩,你不行,可以嗎? – 2010-05-16 00:51:25

+5

首先,你介意給我們展示一個編譯的例子嗎? – 2010-05-16 00:51:30

+0

爲了記錄,你的意思是兩個構造函數*在同一個類中*具有相同的簽名? – harpo 2010-05-16 01:23:25

回答

15

你最好之所以認爲你想做到這一點的是,你發現自己在一個情況下變量類型是不夠的情況下。例如,我可能會欺騙自己,認爲我需要給我的Point類兩個構造函數:一個由X和Y工作,一個按度和弧度工作。兩者都可能被表示爲浮動。

所以我想我需要兩個具有相同簽名(float,float)的構造函數。

Dr.布洛克指出,這是更好地使工廠方法:


    public static Point newPointByDegreesAndRadians (float degrees, float radians); 
    public static Point newPointByXandY (float x, float y); 

順便說一句,另一個替代工廠方法是創建攜帶其從數據類型缺少上下文類型,就像這樣:


    public class CoordinatesXY { 
     float X; 
     float Y; 
     ... 
    } 
    public class CoordinatesDegreesRadians { 
     float degrees; 
     float radians; 
     ... 
    } 
    public Point (CoordinatesXY coordinates) { ... } 
    public Point (CoordinatesDegreesRadians coordinates) { ... } 

無論你認爲這比工廠方法更清晰,這是一個品味問題。對於這個特定情況,我自己的感覺是,如果您的設計使座標獨立使用,與這些座標上的點分離,那麼這兩個座標類僅用於使用。

5

一個類不能有兩個具有相同簽名的構造函數。

From the JLS

8.8.2構造簽名

它是一個編譯時間錯誤,在一類覆蓋當量(§8.4.2)簽名聲明兩個構造函數。聲明兩個簽名在類中具有相同擦除(§4.6)的構造函數是編譯時錯誤。

+2

我知道Java不允許這樣做。這就是爲什麼我們需要靜態工廠。但爲什麼我們需要在這個地方創建不同的構造函數。 – unj2 2010-05-16 02:05:57

2

你不會,你也不能。它不會將類文件編譯爲字節碼,因爲程序無法區分它們以決定使用哪一個。

+0

實際上,重載決議發生在編譯時,所以程序將永遠不會存在試圖找到正確的構造函數。 – Joey 2010-05-16 00:55:24

+4

這不是我說的,還是我誤解了你? – AaronM 2010-05-16 00:59:58

1

@ kunjaan - 即使存在一種技術上有效的方法(在Java中沒有 - 請參閱其他答案),這樣的想法很少有用例。

一個可能的用例是基於某些外部條件的不同構造函數實現 - 例如,如果該構造函數不可用,則可以分配某些內存的構造函數,或者在程序中從某個公共池重用該內存變得可用。

另一個例子是一個構造函數,如果當前體系結構支持該系統調用,它將使用更高效的系統調用來實現某些特定的功能。順便說一句,這兩個例子在Java中都有點難以想象,但在C++ -land中更容易想象,但希望能得到整體想法。

在任何一種情況下,實際上都可以通過具有您提及的工廠進行編碼,或者具有一個構造函數,該構造函數實現某種基於環境的決策並調用具有不同簽名的輔助方法以實際執行所需的初始化這是依賴於實現的,例如(僞代碼,語言無關)

function helper_initializer(signature for case 1) { 

} 
function helper_initializer(signature for case 2) { 

} 
function constructor() { 
    // constructor logic here 
    if (environmental_consdition() == 1) { 
     this->helper_initializer(signature for case 1); 
    } else { 
     this->helper_initializer(signature for case 2); 
    } 
} 
3

要回答你的新編輯的問題,意圖是如果你有一個類可能有兩個邏輯上不同的動作,但碰巧是相同的簽名。

例如,假設您有一個Person類,該類關心某人的姓名和出生地點。

public Person(String name) { ... } 
public Person(String placeOfBirth) { ... } 

很明顯,這是行不通的。

你必須使用一個工廠:

public static Person personWithName(String name) { ... } 
public static Person personFromPlace(String placeOfBirth) { ... } 

顯然,一個人爲的例子,但這是一般的想法...

+0

這是一個很好的例子。 – unj2 2010-05-16 02:14:59

11

你想有兩個(或更多)的構造與原因相同的簽名是數據類型不是意義的同義詞。

一個簡單的例子就是一個Line類。

下面是一個構造:public class Line(double x1, double y1, double x2, double y2)

這裏的另一個:public class Line(double x1, double y1, double angle, double distance)

第一個構造限定了線的兩個端點。第二個構造函數定義了一個終點,以及到第二個終點的角度和距離。

Java無法區分兩個Line類構造函數,true。但是有兩個或更多的構造函數具有相同的簽名有很好的理由。

+1

+1 - 第一句話是關鍵。 – 2010-05-16 03:11:20