views:

142

answers:

2

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

+10  A: 

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.

Ken Bloom
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.
Ken Bloom
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`.
Seth Tisue
I've edited my answer to clarify that you need `val` to access `a.x` in the body of `equals`.
Ken Bloom
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.
Jesper
+5  A: 

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 ==.

David Winslow