2

I'm currently learning Scala and haven't programmed much the last few years, so I may have forgot some OOP fundamentals.

I'm trying to implement the two classes:

case class Rectangle(a : Int,b : Int) extends Shape case class Square(a : Int) extends Shape 

The trait/abstract class (I tried both, neither works) Shape is defined as follows:

trait Shape { def a : Double def b : Double def area = a *b def sides = 4 def perimeter = 2 * (a+b) def equals(r: Shape){ r.a == this.a && r.b == this.b } } 

The desired behavior is Rectangle(2,2) == Square(2)

I thought it should work like this as the operator == should use the equals method which I expect to use the most specific implementation (default implementation when called with some random class and my implementation when called with another Shape as argument.

So, my questions are:

  • How could this be implemented?
  • Is there a reason this should not be implemented (e.g. it is in conflict with some OOP principles, though it would be transitive, reflexive and symmetric)
  • Should Shape be an abstract class or a trait?

2 Answers 2

1

I've found this set of slides that solved the problem (and at least answers the 1st of my questions): https://www.slideshare.net/knoldus/object-equality-inscala (p9)

The problem seems to be that it's necessary to override the built-in equals method and not only adding an additional overload.

override def equals(other : Any) : Boolean = other match{ case s: Shape => s.a == this.a && s.b == this.b case _ => false } 

In my tests so far this works as desired.

On slide 13 it mentions that "equals" should only return true, if their hashcodes are also identical (which is not the case).

Sign up to request clarification or add additional context in comments.

1 Comment

Remember to override hashcode as well if when you override equals so that they remain consistent.
0

Instead of overriding equals method, you need to overload == operator in Shape.

Please see below for more information about operator overloading.

https://docs.scala-lang.org/tour/operators.html

Edit:

Apparently, my initial answer was not clear enough. See sample below:

 abstract class Shape(val a: Int, val b: Int) { def ==(other: Shape): Boolean = this.a == other.a && this.b == other.b } class Square(s: Int) extends Shape(s, s) class Rectangle(x: Int, y: Int) extends Shape(x, y) def main (args: Array[String] ): Unit = { println(new Square(2) == new Rectangle(2, 2)) // true println(new Square(2) == new Rectangle(4, 2)) // false println(new Square(2).equals(new Rectangle(4, 1))) // false } 

3 Comments

I think this is just plain wrong. Everything I've found states that "==" falls back on the equals(x : Any) method. Your link also does not contain anything relevant to the question(s) asked.
Indeed, it seems to work. Though slide #10 here slideshare.net/knoldus/object-equality-inscala seems to advise against doing this. Also I've changed your method to reflect the equality intended in the question.
@oerpli as the slides states, this is a discouraged feature, because it makes code hard to read. I have tried to show you the way to do it. Instead of overriding == operator, I suggest you to create another method like "compare" etc.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.