|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
[scala] How to implement equals methodHi, I saw some code that uses pattern matching to
implement equals method. As pattern matching uses instanceof, that method is not symmetric. class Base(val v1: Int) { override def equals(that: Any) = that match { case other: Base => other.v1 == v1 case _ => false } // ... } class Sub(v1: Int, val v2: Int) extends Base(v1) { override def equals(that: Any) = that match { case other: Sub => other.v1 == v1 && other.v2 == v2 case _ => false } // ... } shanai@shanai-desktop:~$ scala Welcome to Scala version 2.7.1.final (IBM J9 VM, Java 1.6.0). Type in expressions to have them evaluated. Type :help for more information. scala> :l test.scala Loading test.scala... defined class Base defined class Sub scala> val b = new Base(1) b: Base = Base@71547154 scala> val s = new Sub(1, 2) s: Sub = Sub@7d497d49 scala> b == s res0: Boolean = true scala> s == b res1: Boolean = false It breaks the contract of equals method. To make the method symmetric, I can add getClass: class Base(val v1: Int) { override def equals(that: Any) = that match { case other: Base => other.getClass == getClass && other.v1 == v1 case _ => false } //... } // As same for Sub But it seem a bit redundant. Any body knows smarter implementation? Thanks, -- Ruimo Uno (Shisei Hanai) |
|
|
Re: [scala] How to implement equals methodgetClass is a common approach, though it might break down if you don't
define equality exactly along class-based lines. Scala case classes use synthetic integer tags for equality, so the built in case class method will ignore inheritance. I suggest sticking with getClass, unless you have generics and type parameters to worry about, then you have no choice to but to come up with your own tagging scheme. On Sun, Jul 6, 2008 at 9:34 AM, Ruimo Uno <ruimo.uno@...> wrote: > Hi, I saw some code that uses pattern matching to > implement equals method. As pattern matching uses > instanceof, that method is not symmetric. > > class Base(val v1: Int) { > override def equals(that: Any) = that match { > case other: Base => other.v1 == v1 > case _ => false > } > // ... > } > > class Sub(v1: Int, val v2: Int) extends Base(v1) { > override def equals(that: Any) = that match { > case other: Sub => other.v1 == v1 && other.v2 == v2 > case _ => false > } > // ... > } > > shanai@shanai-desktop:~$ scala > Welcome to Scala version 2.7.1.final (IBM J9 VM, Java 1.6.0). > Type in expressions to have them evaluated. > Type :help for more information. > > scala> :l test.scala > Loading test.scala... > defined class Base > defined class Sub > > scala> val b = new Base(1) > b: Base = Base@71547154 > > scala> val s = new Sub(1, 2) > s: Sub = Sub@7d497d49 > > scala> b == s > res0: Boolean = true > > scala> s == b > res1: Boolean = false > > It breaks the contract of equals method. To make the > method symmetric, I can add getClass: > > class Base(val v1: Int) { > override def equals(that: Any) = that match { > case other: Base => other.getClass == getClass && other.v1 == v1 > case _ => false > } > //... > } > > // As same for Sub > > But it seem a bit redundant. Any body knows smarter > implementation? > > Thanks, > > -- > Ruimo Uno > (Shisei Hanai) > |
|
|
|
|
|
Re: [scala] How to implement equals methodThe equals method is a general pain, regardless of Scala. It's all about thinking ahead on what you want to do with your classes...
On Mon, Jul 7, 2008 at 4:06 AM, Sean McDirmid <sean.mcdirmid@...> wrote: Ah, its probably changed. Anyways, maybe tags are used for traits or -- __~O -\ <, Christos KK Loverdos (*)/ (*) http://ckkloverdos.com |
|
|
Re: [scala] How to implement equals methodI eventually realized using isComparable method shown in 'Programming
in Scala' book seems the best choice. I'm not sure why the current Scala's generated code for the equals method of case class does not conform to this technique, though. Maybe for compatibility issue... On Mon, Jul 7, 2008 at 10:06 AM, Sean McDirmid <sean.mcdirmid@...> wrote: > Ah, its probably changed. Anyways, maybe tags are used for traits or > maybe that aren't used at all anymore :) You could use instanceof > tests like case classes, note that equality is no longer symmetric > when you have case classes extending other case classes, basically > because equals is overridden on a per class, not class pair basis. > > Sean > > On Sun, Jul 6, 2008 at 9:00 PM, Shisei Hanai <shanai@...> wrote: >> I tested the following code: >> >> case class Base >> case class Sub(i: Int) extends Base >> >> object Test { >> def main(args: Array[String]) { >> val b = Base() >> val s = Sub(1) >> System.out.println(b.equals(s)) >> } >> } >> >> Compiler emits the following code for Base.equals: >> >> public boolean equals(java.lang.Object); >> Code: >> Stack=2, Locals=3, Args_size=2 >> 0: aload_1 >> 1: instanceof #8; //class java/lang/Object >> 4: ifeq 25 >> 7: aload_0 >> 8: aload_1 >> 9: if_acmpeq 21 >> 12: aload_1 >> 13: astore_2 >> 14: aload_2 >> 15: instanceof #46; //class Base >> 18: ifeq 25 >> 21: iconst_1 >> 22: goto 26 >> 25: iconst_0 >> 26: ireturn >> LineNumberTable: >> line 1: 0 >> >> LocalVariableTable: >> Start Length Slot Name Signature >> 0 27 0 this LBase; >> 0 27 1 x$1 Ljava/lang/Object; >> >> Even for case classes, Scala uses instanceof for type equality. As a >> result, the Test.main prints true. >> >> shanai@shanai-laptop:/tmp$ scala Test >> true >> >> Do you mean future version of Scala? I'm using 2.7.1-final >> >> Scala compiler version 2.7.1.final -- Copyright 2002-2008, LAMP/EPFL >> >> Thanks, >> >> 2008/7/6 Sean McDirmid <sean.mcdirmid@...>: >>> getClass is a common approach, though it might break down if you don't >>> define equality exactly along class-based lines. Scala case classes >>> use synthetic integer tags for equality, so the built in case class >>> method will ignore inheritance. >>> >>> I suggest sticking with getClass, unless you have generics and type >>> parameters to worry about, then you have no choice to but to come up >>> with your own tagging scheme. >>> >>> On Sun, Jul 6, 2008 at 9:34 AM, Ruimo Uno <ruimo.uno@...> wrote: >>>> Hi, I saw some code that uses pattern matching to >>>> implement equals method. As pattern matching uses >>>> instanceof, that method is not symmetric. >>>> >>>> class Base(val v1: Int) { >>>> override def equals(that: Any) = that match { >>>> case other: Base => other.v1 == v1 >>>> case _ => false >>>> } >>>> // ... >>>> } >>>> >>>> class Sub(v1: Int, val v2: Int) extends Base(v1) { >>>> override def equals(that: Any) = that match { >>>> case other: Sub => other.v1 == v1 && other.v2 == v2 >>>> case _ => false >>>> } >>>> // ... >>>> } >>>> >>>> shanai@shanai-desktop:~$ scala >>>> Welcome to Scala version 2.7.1.final (IBM J9 VM, Java 1.6.0). >>>> Type in expressions to have them evaluated. >>>> Type :help for more information. >>>> >>>> scala> :l test.scala >>>> Loading test.scala... >>>> defined class Base >>>> defined class Sub >>>> >>>> scala> val b = new Base(1) >>>> b: Base = Base@71547154 >>>> >>>> scala> val s = new Sub(1, 2) >>>> s: Sub = Sub@7d497d49 >>>> >>>> scala> b == s >>>> res0: Boolean = true >>>> >>>> scala> s == b >>>> res1: Boolean = false >>>> >>>> It breaks the contract of equals method. To make the >>>> method symmetric, I can add getClass: >>>> >>>> class Base(val v1: Int) { >>>> override def equals(that: Any) = that match { >>>> case other: Base => other.getClass == getClass && other.v1 == v1 >>>> case _ => false >>>> } >>>> //... >>>> } >>>> >>>> // As same for Sub >>>> >>>> But it seem a bit redundant. Any body knows smarter >>>> implementation? >>>> >>>> Thanks, >>>> >>>> -- >>>> Ruimo Uno >>>> (Shisei Hanai) >>>> >>> >> >> >> >> -- >> Shisei Hanai (Ruimo Uno) >> http://www.ruimo.com/ >> > -- Ruimo Uno (Shisei Hanai) |
|
|
Re: [scala] How to implement equals methodOn Mon, Jul 7, 2008 at 10:21 AM, Ruimo Uno <ruimo.uno@...> wrote:
> I eventually realized using isComparable method shown in 'Programming > in Scala' book seems the best choice. > I'm not sure why the current Scala's generated code for the equals > method of case class does not conform to this technique, though. Maybe > for compatibility issue... > Right. It would break binary compatibility, so we have to wait for the next major release to do it. Cheers -- Martin |
|
|
Re: [scala] How to implement equals methodI see, I'm looking forward to the future version.
Thanks, On Tue, Jul 8, 2008 at 12:57 AM, martin odersky <martin.odersky@...> wrote: > On Mon, Jul 7, 2008 at 10:21 AM, Ruimo Uno <ruimo.uno@...> wrote: >> I eventually realized using isComparable method shown in 'Programming >> in Scala' book seems the best choice. >> I'm not sure why the current Scala's generated code for the equals >> method of case class does not conform to this technique, though. Maybe >> for compatibility issue... >> > Right. It would break binary compatibility, so we have to wait for the > next major release to do it. > > Cheers > > -- Martin > -- Ruimo Uno (Shisei Hanai) |
| Free Forum Powered by Nabble | Forum Help |