2015-10-20 55 views
1

我的項目中有四個域對象。他們有3個共同的屬性,即id,姓名和年齡。Java對象相等

public class Domain1 { 
     private String id; 
     private String name; 
     private int age; 
     ... 
} 

public class Domain2 { 
     private String id; 
     private String name; 
     private int age; 
     ... 
} 

public class Domain3 { 
     private String id; 
     private String name; 
     private int age; 
     ... 
} 

public class Domain4 { 
     private String id; 
     private String name; 
     private int age; 
     ... 
} 

domain1並Domain4比較僅基於「id」屬性時與其他域(域2,和DOMAIN3 Domain4)相比或與對方。 Domain2和Domain3的比較基於id,名稱和年齡,除非彼此相互比較。

對於離,

Domain1 equal Domain2 - equality based on id 
Domain1 equal Domain3 - equality based on id 
Domain1 equal Domain4 - equality based on id 
Domain2 equal Domain3 - equality based on id, name and attribute 
Domain2 equal Domain4 - equality based on id 
Domain3 equal Domain4 - equality based on id 

等等...

如何實現這樣一個平等的要求?

+3

我通常會說一個類型的實例等於另一個類型的實例是一個壞主意。我不記得曾經看到那種正確和有用的執行。 –

回答

1

您可以根據您的要求只爲overrideequals()方法爲這四個域對象。 您可以通過IDE生成它並進行修改以符合您的要求。

編輯:在你的方法,你可以找對象,你要比較的類型:

public boolean equals(Object object){ 
    if(object instancof Domain4) //Specific implementation 
    .... 
} 

然而,像喬恩表示,將違反的Object.Equals的要求。

+0

謝謝@talhouarne。我的要求是,如果我調用domain1.equals(domain2)或domain2.equals(domain1)它應該做基於id的平等。如果我做domain2.equals(domain3),它應該根據id,名稱和屬性進行平等。我如何在domain2中有兩種不同的實現? – user3222372

+0

看到我的編輯.... – ltalhouarne

+0

@talhouarne,我也不喜歡這種方式。有沒有其他方法可以更好地實現這一目標?我們不斷爲我們的項目引入新的領域,所以如果我們能夠在這裏得到一個好的解決方案將是非常好的。 – user3222372

2

我只是儘量不要這樣做。你提出的規則違反Object.equals的要求,特別是:

傳遞性:對於任何非空引用值x,y和z,如果x.equals(y)返回真和y .equals(z)返回true,那麼x.equals(z)應該返回true。

現在考慮您的規則:

Domain1 d1 = new Domain1("id1", "name1", "attribute1"); 
Domain2 d2 = new Domain2("id1", "name1", "attribute1"); 
Domain3 d3 = new Domain3("id1", "name3", "attribute3"); 

現在d2.equals(d1)是真實的(它們匹配的ID)和d1.equals(d3)是真實的(它們匹配的ID),但d2.equals(d3)是假的,因爲它們不匹配關於屬性和名稱。

我不認爲我記得在完全不同類型的工作很好地看到平等。試圖避免超類/子類關係中的意外已經夠難了,但這種情況更糟。

+0

謝謝@Jon的反饋。你是對的,這不是一個正確的平等用例。它在某些情況下就像部分匹配。有沒有其他的方式來實現這一點像使用comapreTo或某種模式匹配? – user3222372

+0

@ user3222372:好吧,我們不知道你想用這種非標準匹配來實現什麼,這使得很難告訴你如何實現它,除了說「不要這樣做」。 –

+0

我基於上面的等式規則對基於對象的域對象應用業務規則。我們需要在一些數據結構中存儲這些對象並應用業務規則。 – user3222372

0

也許我不是在這裏理解用例,但是你可以試試using a Comparator,然後創建一個ComparableDomain接口,它具有像getType(這會返回Domain1,Domain2等)以及普通getter/setters(for名稱,年齡和id),並讓您的所有域都實現ComparableDomain。

現在,您可以先比較兩個不同的Domain對象,首先詢問它們的類型,然後按照您所描述的步驟檢查這些字段。

public class DomainComparator implements Comparator<ComparableDomain>{ 

    @Override 
    public int compare(ComparableDomain domain1, ComparableDomain domain2) { 
     //First check domain1 and domain2 are actually ComparableDomain objects 
     if(domain1.getType().equals("Domain1") && domain2.getType().equals("Domain2")){ 
      // Do comparison between d1 and d2 
     } 
     ... 
     elseif(domain1.getType().equals("Domain2") && domain2.getType().equals("Domain3"){ 
      // Do comparison based on id, name and attribute 
     } 

    } 

} 

這可能不是很優雅,但它似乎可以解決問題。或者,也許我只是誤解了這個問題。我知道比較器通常用於排序等,但在這種情況下,它可能工作。

+0

謝謝@Acapulco。你正確地理解了這個問題。如果域數量不增長,此解決方案將起作用。我們不斷添加新的域名,這種設計將來不會持續。 – user3222372

+0

是的,我認爲這很難。另一個更復雜的選項是通過配置文件參數化比較。無論何時創建DomainComparator,都會加載配置文件並設置比較不同類型域的規則。這樣你就可以隨心所欲地變得靈活。缺點是您需要編寫小配置加載程序並確保規則按預期工作等。但是我發現,對於很多問題,具有決定內部組件行爲的外部配置文件可能會使事情變得更容易 – Acapulco

+0

所以你可以定義一個類似於狀態機的轉換表的表,然後你可以在一行和一列(兩個域類型)上創建一個十字,以及由該表指定的實際矩陣索引行和列會讓你知道究竟要比較什麼,或者即使這兩個域甚至可以比較開始。這意味着比較規則由行/列交叉確定。現在,這將是一個定義什麼樣的規則的問題。它可能是一個位圖(每個屬性要比較1位,所以101可以是比較ID,忽略名稱,比較年齡) – Acapulco