问题
I have the following case class
case class Something(val input : Array[Int], val output : Array[Int] = null, val remainder : Array[Int] = null, val next : Something = null) {
override def equals(thatGeneric: scala.Any): Boolean = {
if(!thatGeneric.isInstanceOf[Something])
return false
val that = thatGeneric.asInstanceOf[Something]
val thisInput = if(this.input == null) null else this.input.deep
val thatInput = if(that.input == null) null else that.input.deep
val thisOutput = if(this.output == null) null else this.output.deep
val thatOutput = if(that.output == null) null else that.output.deep
val thisRemainder = if(this.remainder == null) null else this.remainder.deep
val thatRemainder = if(that.remainder == null) null else that.remainder.deep
return (thisInput,thisOutput,thisRemainder,this.next) == (thatInput,thatOutput,thatRemainder,that.next)
}
/**
* TODO fix hashcode in case I want to use this in collection
* @return
*/
override def hashCode(): Int = super.hashCode()
}
I know that case classes are supposed to have your equals and hashCode methods created for you but for Arrays since == doesn't work then I guess thats why it doesn't work for my case class.
Is there a better way to not have to hand-write my equals and hashCode methods for my case class?
Note: I also welcome advice on why/how to improve my current equals method
Edit: Do appreciate the notes about my use of case class in general, but my question was basically: Assume you have the need of an Array in your case class, how do you avoid rolling your own equals and hashCode. (If the answer is that its impossible and I need to use a list then that is the answer, just not sure that is the case.)
回答1:
Array is indeed lighter, but, unfortunately, not by much (scala doesn't reimplement most of the methods for the array, so they end up sharing the generic (sucky) scala collection performance properties.
As long as you are set on using arrays, you'll have to implement your own equals, not much that you can do about that, but you can make it look prettier, like this:
def eq[T](a: Array[T], b: Array[T]) = Option(a.toSeq) == Option(b.toSeq)
def equals(that: Something) =
eq(input, that.input) &&
eq(output, that.output) &&
eq(remainder, that.remainder) &&
next == that.next
You should consider making your variable optional though. Like everybody says, null isn't going to score you any points in scala.
Also, again, like everybody else said, reconsider having your case class as a class: the whole point of using case classes is getting equals and hashCode (and some other stuff) for free. If you are going to reimplement all of that anyway, declaring it as a case class if just confusing, and has no benefit.
回答2:
There seems to be a couple things wrong with this class definition. The use of nulls, vars, and Arrays.
As @m-z made mention, case classes are intended to be used as "data" classes. Data which should be immutable. If you don't want to have to roll your own equals and hashCode then you should rethink the implementation.
Note: Not sure what you are trying to use this class for but there might be a design pattern that probably fits your needs and adhere to the true use of case classes.
来源:https://stackoverflow.com/questions/38341016/case-class-equality-for-arrays