This page is no longer maintained — Please continue to the home page at www.scala-lang.org

hashCode(), equals() and toString() without case classes

3 replies
Ruediger Keller 2
Joined: 2010-04-30,
User offline. Last seen 42 years 45 weeks ago.

Hello list,

it seems that questions about case classes and warnings about case
class inheritance are quite frequent on this list.

Often this boils down to case classes being used for their convenient
default implementation of hashCode(), equals() and toString(). I
thought maybe it was nice if these default implementations were
available without using case classes. I read somewhere that
scala.runtime.ScalaRuntime has methods that can be used for this. But
this would require you to extend Product and set up your class
accordingly, writing the appropriate delegate methods. This still
seems to add a lot of boilerplate code.

I wonder whether it is feasible to introduce an annotation or
something alike for this. Maybe something like @ValueClass. Adding it
to a class would make the compiler add the appropriate hashCode(),
equals() and toString() methods to the class like for a case class.

Would this be even possible? Would it be a lot of effort to implement?
Would it imply the same inheritance restrictions as case classes have?

For the people with experience on compiler plugins. Do you think it
would be hard to write a plugin for this? I think Kevin Wright wrote
something about adding methods being quite hard to do in a plugin, but
I guess this doesn't apply here, as these methods are all already
defined in java.lang.Object.

Regards,
Ruediger

Kevin Wright
Joined: 2009-06-09,
User offline. Last seen 49 weeks 3 days ago.
Re: hashCode(), equals() and toString() without case classes
It's true!
Adding synthetic methods that already exist (because they're inherited from a superclass) is an absolute doddle, because the thing type-checks cleanly even before the synthetics are added.
I probably wouldn't do this with an annotation though, and would favour a trait instead.
  class Foo extends Bar with SyntheticEquality
Like I said, the plugin could act after the typer phase, so checking for SyntheticEquality in the inheritance graph is no great pain.
SyntheticEquality would itself subclass Product and, to avoid the risk that the program might "accidentally" be compiled without the plugin, I'd have it implement Product's methods to all simply throw an exception - this behaviour to be rewritten by the plugin.

On 30 April 2010 15:08, Ruediger Keller <ruediger [dot] keller [at] rk42 [dot] de> wrote:
Hello list,

it seems that questions about case classes and warnings about case
class inheritance are quite frequent on this list.

Often this boils down to case classes being used for their convenient
default implementation of hashCode(), equals() and toString(). I
thought maybe it was nice if these default implementations were
available without using case classes. I read somewhere that
scala.runtime.ScalaRuntime has methods that can be used for this. But
this would require you to extend Product and set up your class
accordingly, writing the appropriate delegate methods. This still
seems to add a lot of boilerplate code.

I wonder whether it is feasible to introduce an annotation or
something alike for this. Maybe something like @ValueClass. Adding it
to a class would make the compiler add the appropriate hashCode(),
equals() and toString() methods to the class like for a case class.

Would this be even possible? Would it be a lot of effort to implement?
Would it imply the same inheritance restrictions as case classes have?

For the people with experience on compiler plugins. Do you think it
would be hard to write a plugin for this? I think Kevin Wright wrote
something about adding methods being quite hard to do in a plugin, but
I guess this doesn't apply here, as these methods are all already
defined in java.lang.Object.

Regards,
Ruediger



--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

Ruediger Keller 2
Joined: 2010-04-30,
User offline. Last seen 42 years 45 weeks ago.
Re: hashCode(), equals() and toString() without case classes

Kevin, thanks for your insights!

Perhaps if I find some spare time I will try to write a compiler
plugin for this.

Am I right that this approach would not have the same problems with
inheritance as case classes have?

Regards,
Ruediger

2010/4/30 Kevin Wright :
> It's true!
> Adding synthetic methods that already exist (because they're inherited from
> a superclass) is an absolute doddle, because the thing type-checks cleanly
> even before the synthetics are added.
> I probably wouldn't do this with an annotation though, and would favour a
> trait instead.
>   class Foo extends Bar with SyntheticEquality
> Like I said, the plugin could act after the typer phase, so checking for
> SyntheticEquality in the inheritance graph is no great pain.
> SyntheticEquality would itself subclass Product and, to avoid the risk that
> the program might "accidentally" be compiled without the plugin, I'd have it
> implement Product's methods to all simply throw an exception - this
> behaviour to be rewritten by the plugin.
>
> On 30 April 2010 15:08, Ruediger Keller wrote:
>>
>> Hello list,
>>
>> it seems that questions about case classes and warnings about case
>> class inheritance are quite frequent on this list.
>>
>> Often this boils down to case classes being used for their convenient
>> default implementation of hashCode(), equals() and toString(). I
>> thought maybe it was nice if these default implementations were
>> available without using case classes. I read somewhere that
>> scala.runtime.ScalaRuntime has methods that can be used for this. But
>> this would require you to extend Product and set up your class
>> accordingly, writing the appropriate delegate methods. This still
>> seems to add a lot of boilerplate code.
>>
>> I wonder whether it is feasible to introduce an annotation or
>> something alike for this. Maybe something like @ValueClass. Adding it
>> to a class would make the compiler add the appropriate hashCode(),
>> equals() and toString() methods to the class like for a case class.
>>
>> Would this be even possible? Would it be a lot of effort to implement?
>> Would it imply the same inheritance restrictions as case classes have?
>>
>> For the people with experience on compiler plugins. Do you think it
>> would be hard to write a plugin for this? I think Kevin Wright wrote
>> something about adding methods being quite hard to do in a plugin, but
>> I guess this doesn't apply here, as these methods are all already
>> defined in java.lang.Object.
>>
>> Regards,
>> Ruediger
>
>
>
> --
> Kevin Wright
>
> mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
> wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
> skype: kev.lee.wright
> twitter: @thecoda
>
>

Kevin Wright
Joined: 2009-06-09,
User offline. Last seen 49 weeks 3 days ago.
Re: hashCode(), equals() and toString() without case classes
Won't say I'll stake my life on it, but I can't think of any issues at the moment why this should be any riskier than just defining your own equals and hashCode methods by hand :)



On 30 April 2010 15:33, Ruediger Keller <ruediger [dot] keller [at] rk42 [dot] de> wrote:
Kevin, thanks for your insights!

Perhaps if I find some spare time I will try to write a compiler
plugin for this.

Am I right that this approach would not have the same problems with
inheritance as case classes have?

Regards,
Ruediger


2010/4/30 Kevin Wright <kev [dot] lee [dot] wright [at] googlemail [dot] com>:
> It's true!
> Adding synthetic methods that already exist (because they're inherited from
> a superclass) is an absolute doddle, because the thing type-checks cleanly
> even before the synthetics are added.
> I probably wouldn't do this with an annotation though, and would favour a
> trait instead.
>   class Foo extends Bar with SyntheticEquality
> Like I said, the plugin could act after the typer phase, so checking for
> SyntheticEquality in the inheritance graph is no great pain.
> SyntheticEquality would itself subclass Product and, to avoid the risk that
> the program might "accidentally" be compiled without the plugin, I'd have it
> implement Product's methods to all simply throw an exception - this
> behaviour to be rewritten by the plugin.
>
> On 30 April 2010 15:08, Ruediger Keller <ruediger [dot] keller [at] rk42 [dot] de> wrote:
>>
>> Hello list,
>>
>> it seems that questions about case classes and warnings about case
>> class inheritance are quite frequent on this list.
>>
>> Often this boils down to case classes being used for their convenient
>> default implementation of hashCode(), equals() and toString(). I
>> thought maybe it was nice if these default implementations were
>> available without using case classes. I read somewhere that
>> scala.runtime.ScalaRuntime has methods that can be used for this. But
>> this would require you to extend Product and set up your class
>> accordingly, writing the appropriate delegate methods. This still
>> seems to add a lot of boilerplate code.
>>
>> I wonder whether it is feasible to introduce an annotation or
>> something alike for this. Maybe something like @ValueClass. Adding it
>> to a class would make the compiler add the appropriate hashCode(),
>> equals() and toString() methods to the class like for a case class.
>>
>> Would this be even possible? Would it be a lot of effort to implement?
>> Would it imply the same inheritance restrictions as case classes have?
>>
>> For the people with experience on compiler plugins. Do you think it
>> would be hard to write a plugin for this? I think Kevin Wright wrote
>> something about adding methods being quite hard to do in a plugin, but
>> I guess this doesn't apply here, as these methods are all already
>> defined in java.lang.Object.
>>
>> Regards,
>> Ruediger
>
>
>
> --
> Kevin Wright
>
> mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
> wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
> skype: kev.lee.wright
> twitter: @thecoda
>
>



--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland