Simple Scala syntax - trying to define "==" operator - what am I missing?
Asked Answered
J

2

8

While experimenting with some stuff on the REPL, I got to a point where I needed something like this:

scala> class A(x:Int) { println(x); def ==(a:A) : Boolean = { this.x == a.x; } }

Just a simple class with an "==" operator.

Why doesn't it work???

Here's the result:

:10: error: type mismatch;
 found   : A
 required: ?{val x: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
 and method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
 are possible conversion functions from A to ?{val x: ?}
       class A(x:Int) { println(x); def ==(a:A) : Boolean = { this.x == a.x; } }
                                                                        ^

This is scala 2.8 RC1.

Thanks

Jannery answered 21/4, 2010 at 1:42 Comment(0)
S
17

You have to define the equals(other:Any):Boolean function, then Scala gives you == for free, defined as

class Any{
  final def == (that:Any):Boolean =
    if (null eq this) {null eq that} else {this equals that}
}

See chapter 28 (Object Equality) of Programming in Scala for more on how to write the equals function so that it's really an equivalence relation.

Moreover, the parameter x that you pass to your class isn't stored as a field. You need to change it to class A(val x:Int) ..., and then it will have an accessor that you can use to access a.x in the equals operator.

Savour answered 21/4, 2010 at 1:57 Comment(4)
I suppose it's more accurate to say that it's not accessible as a field i.e. it doesn't generate accessor methods unless you declare it as a val when you pass it in.Savour
Mm hmm. Alex may want to add val for other reasons, but someone could read your answer as implying that it's needed in order to access x in the body of equals.Nucleolar
I've edited my answer to clarify that you need val to access a.x in the body of equals.Savour
You can also do: class A(private val x: Int) if you don't want x to be visible as a field from outside the class.Melba
D
7

The error message is a little confusing because of coincidence with some code in Predef. But what's really going on here is that you're trying to call the x method on your A class, but no method with that name is defined.

Try:

class A(val x: Int) { println(x); def ==(a: A): Boolean = { this.x == a.x } }

instead. This syntax makes x a member of A, complete with the usual accessor method.

As Ken Bloom mentioned, however, it's a good idea to override equals instead of ==.

Deangelis answered 21/4, 2010 at 1:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.