Ці будзе пераазначэнне Equals () з множнымі выпрабаваннямі InstanceOf быць магчымым для розных аб'ектаў?

Скажам, у мяне ёсць клас, дзе я павінен быў бы праверыць на некалькі розных тыпаў аб'ектаў. Ці будзе гэта магчыма/можна перавызначыць роўны() наступным чынам?

public boolean equals(Object o){
    if(o == null) return false;
    if(o instanceof class1){
        return this.class1.equals((class1) o);
    if(o instanceof class2){
        return this.class2.equals((class2) o);
    ...

}

Ці будзе гэта калі-небудзь быць карысным? Я мяркую, што тут, што я ствараю статычны перагружаны роўны() метад у адпаведных класах (хоць, магчыма, палімарфізм будзе клапаціцца аб тым, што аўтаматычна, пакуль я кідаю?).

1
Глядзіце таксама stackoverflow.com/questions/596462/…
дададзена аўтар Raedwald, крыніца
Гэты код з'яўляецца законным, так што гэта магчыма. Але гэта не вельмі добрая ідэя, каб сказаць, што два аб'екта роўныя, калі яны таго ж класа. Калі вы вырашылі ажыццявіць такі эксперымент, правільны спосаб зрабіць гэта ў OO, каб перавызначыць роўна ў кожным падклас.
дададзена аўтар Mister Smith, крыніца
Дзякуй за вашыя вялікія каментары.
дададзена аўтар user991710, крыніца
Ня @CedricMartin праўда, вы можаце. Вы проста не можаце дадаваць атрыбуты падкласаў, якія змяняюць роўнасць. Ну і нават папярэдняе прапанова з'яўляецца няправільным: Вы можаце рэалізаваць роўна правільна (г.зн. без парушэння якога-небудзь гарантаваных матэматычных уласцівасцяў адносіны роўнасці), нават тады, гэта проста наогул не тое, што хто-небудзь хоча - дык гэта мае невялікае практычнае значэнне. На самай справе Одерская напісаў артыкул, якая паказвае, як зрабіць гэта. Edit: Ці вы проста кажаце, што вы не можаце гарантаваць, што падкласы рэалізаваць гэта правільна? Праўда, але тое ж самае для многіх рэчаў, якія я б сказаў.
дададзена аўтар Voo, крыніца
@CedricMartin Одерская ўсё яшчэ выкарыстоўвае роўныя, але з дапаможным метадам. І, вядома, я напісаў падкласы, якія не змяняюць паводзіны такім чынам і працуюць нармальна. І нават сітуацыі, калі я дадаў атрыбуты і быў добра з падкласа заўсёды ацэньваць не роўныя па параўнанні з яго бацькам. Але як бы вы вырашыць асноўную праблему? Я не разумею, як гэта важна, дзе вы рэалізуеце роўна - як толькі вы параўнайце супер з падкласа гэтыя праблемы проста паўзуць уверх. Што было б прапанаванае рашэнне?
дададзена аўтар Voo, крыніца
@CedricMartin Не, мы не Ці не <б /> транзітыўнасць разрыў, што КОЖНЫ матэматычнае Уласцівасць роўна стаўленне павінна мець можа быць гарантаваная. Ды нам патрэбны дадатковы метад, калі мы перазапісаць роўных, ды рашэнне не абавязкова з'яўляецца інтуітыўна - і? Калі ваша рашэнне «Ну проста не выкарыстоўваць роўныя» - я думаю, што я пайду з «не ідэальным рашэннем» замест не выкарыстоўваючы нічога. Павінна быць цікава праграмаваць ў рэжыме рэальнага OOP зямлі без HashMaps, упарадкаваных калекцыі і што-небудзь яшчэ, дзе патрэбныя два метаду. Я думаю, што я аддаю перавагу практычнае рашэнне.
дададзена аўтар Voo, крыніца
гэта можа быць «карысным» у залежнасці ад таго, што вы робіце, але вы павінны ведаць, што з <я> роўна і <я> хэш-код у верхняй частцы іерархіі Java з'яўляецца чыста і проста памылковыя. Там няма ніякага спосабу вакол яго. Вы не можаце гарантаваць РОЎНА/Hashcode кантрактаў, як толькі ў вас ёсць спадчыну. Як проста. невыканальная . Гэта прыгожа і вельмі выразна і недвухсэнсоўна растлумачыць Джошуа Блох ў Эфектыўнае Java . Там таксама вялікая гутарка Одерская (ад Scala славы) па гэтым пытанні на Artima.
дададзена аўтар Cedric Martin, крыніца
@Voo: Одерская напісаў артыкул, якая паказвае адзін дзень, каб абыйсці гэтую праблему, <я> без выкарыстання роўных() і хэш-код() (ён стварае іншыя метады). Джошуа Блох сказаў наступнае: <я> «Там проста няма спосабу накіраваць инстанциируемый клас і дадаць аспект пры захаванні кантракту роўных» . Так што я стаю на маё сцвярджэнне, што калі вы хочаце выкарыстоўваць спадчыну (які, ды, як правіла, азначае наяўнасць класаў і падкласаў), то <я> роўна і <я> хэш-код у верхняй частцы іерархіі ГА у Java зламаныя. Я не спрачаюся, ёсць абыходны шлях: я проста стан, што <я> роўна і <я> хэш-код не павінен быў там.
дададзена аўтар Cedric Martin, крыніца
@Voo: цяпер я не спрачаюся, што калі вы не зробіце OO, напрыклад, калі вы выкарыстоўваеце Java ў працэдурным спосабам і заўсёды ставіць сапраўды такі ж выгляд аб'ектаў у калекцыі, а затым <я> роўна і <я> хэш-код зрабіць працу :) Так што гэта зводзіцца да: <я> «вы можаце, калі вы не дадаеце аспект/атрыбуты падкласаў» , але тады мы сапраўды гаворым аб атрыманнi спадчыны і ГА !?
дададзена аўтар Cedric Martin, крыніца
@Voo: <я> "І нават сітуацыі, калі я дадаў атрыбуты і быў добра з падкласа заўсёды ацэнка не роўная" , але тады вы зламалі transivity (<я> Effective Java ). І так гэта поўнае кола, я буду сцвярджаць яшчэ раз дакладнае прапанову Джошуа Блох напісаў у Effective Java: <я> «Там проста няма спосабу накіраваць инстанциируемый клас і дадаць аспект пры захаванні кантракту РОЎНА» , Вы можаце спрачацца з Джошуа Блох столькі, колькі вы хочаце: вы <б> зрабіў разарваць кантракт роўна . Прапанаванае рашэнне? Дапускаюць, што <я> роўна і <я> хэш-код былі зламаныя, спыніць іх выкарыстанне ці перастаць рабіць выгляд, што вы робіце OO.
дададзена аўтар Cedric Martin, крыніца
@Voo: вы таксама зручна забывае адзначыць, што Одерская сцвярджае, што яго рашэнне не з'яўляецца дасканалым (і гэта не зроблена, выкарыстоўваючы дапаможны метад, гэта робіцца з дапамогай метаду, які павінен прысутнічаць <б> у кожным аб'екце, дзе на роўных і хэш-код прысутнічае ). Цяпер спыніць яго!
дададзена аўтар Cedric Martin, крыніца

4 адказы

I very much doubt that because you can easily violate the transitivity of equals this way (x.equals(y) && x.equals(z) implies y.equals(z))

калі, вядома, вы не робіце вельмі ўсю ўстаноўку з удзелам усіх класаў, але гэта было б боль, каб атрымаць права

3
дададзена
Шкада, я не магу выбраць некалькі адказаў!
дададзена аўтар user991710, крыніца

Падобна на тое, што вы хочаце спосаб праверыць, ці з'яўляецца роўна, па меншай меры, аднаго з розных зменных членаў у прыёмніку ўказаны аб'ект.

Немэтазгодна перавызначыць java.lang.Object # роўна для гэтай мэты.

Замест гэтага вы павінны даць іншы спосаб, напрыклад,

public boolean hasEquals(Object o) {//your impl }
1
дададзена

Семантычны я не думаю, што гэта добрая ідэя. Роўна не павінны быць заснаваныя на тыпах класаў, але зменныя асобніка. Акрамя таго, яблык ніколі не павінна быць роўна грушай, але толькі з іншымі яблыкамі.

1
дададзена

Калі вы ўпэўненыя, што гэта не прывядзе да ўзаемнай рэкурсіі вы можаце проста вярнуцца that.equals (гэта) . Аднак увогуле аб'ектнага роўнасць мяркуе альбо роўнасць класаў, або, па меншай меры, кагерэнтнай адносіны ў спадчыну паміж імі.

0
дададзена