2016-07-13 2 views
1

Я следующий случай классучехла класс равенство Массивы

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() 
} 

Я знаю, что классы случае должны иметь свои равные и методы Hashcode, созданные для вас, но для массивов, начиная с == не работаю, то я думаю, вот почему это не работает для моего класса case.

Есть ли лучший способ не писать вручную мои методы equals и hashCode для моего класса case?

Примечание: Я также приветствую советы о том, почему/как улучшить мой ток равен методу

Edit: Не ценят заметки о моем использовании прецедентного класса в целом, но мой вопрос был в основном: Предположим, у вас есть необходимость из массива в вашем классе case, как вы избегаете перематывать свои собственные равные и hashCode. (Если ответ заключается в том, что его невозможно, и мне нужно использовать список, то это ответ, просто не уверен, что это так.)

+1

Есть ли причина, по которой вы хотите использовать 'Array', а не' List'? Класс случая традиционно предназначен для хранения неизменной структуры данных. –

ответ

1

Кажется, что в этом определении класса есть пара ошибок. Использование null s, var s, и Array s.

Как указано в @ m-z, классы case предназначены для использования в качестве классов данных. Данные, которые должны быть неизменными. Если вы не хотите перематывать свои собственные equals и hashCode, вам следует пересмотреть реализацию.

Примечание. Не уверен, что вы пытаетесь использовать для этого класса, но может быть шаблон дизайна, который, вероятно, соответствует вашим потребностям и придерживается истинного использования классов case.

+0

На самом деле он неизменен, я изначально имел его как 'var', но они могут быть 'val' без проблем. Не уверен, что вы имеете в виду проблема с 'nulls' и' Array'. Вы можете объяснить? –

+0

Вы можете использовать 'val', но сам массив по-прежнему изменен. По-видимому, вы хотите, чтобы ** содержимое ** массива учитывалось при вычислении хэш-кода, но здесь кроется проблема: этот контент может измениться, что изменит хэш-код и разорвет контракт метода hashCode («Всякий раз, когда он вызывается одним и тем же объектом более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число», см. Https://docs.oracle.com/javase/7/docs/api/ Java/Util/Objects.html # хэш-код (java.lang.Object)). –

+0

@ RégisJean-Gilles это не вопрос использования изменяемого типа в качестве аргументов для вашего класса case. Например, вы можете использовать 'mutable.Seq', а классы case с тем же содержимым все равно будут равны. Речь идет о том, как выполняется равенство для 'Array' и' Iterator', которое является ссылочным равенством. См. Http://stackoverflow.com/q/3737711/552902 – JRomero

2

Массив является действительно легче, но, к сожалению, не много (не Scala переописать большинство методов массива, так что они в конечном итоге разделяя общие (Sucky) эксплуатационные свойства коллекции Scala.

Как пока вы настроены на использование массивов, вам придется реализовать свой собственный equals, не так много, что вы можете сделать об этом, но вы можете сделать это выглядеть симпатичнее, как это:

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 

вы должны рассмотреть вопрос о внесении ваша переменная необязательна, хотя. Как и все говорят, null не собирается забивать у вас какие-либо очки в sca л.

Кроме того, как и все остальные, повторное рассмотрение вопроса о том, что ваш класс является классом case: вся цель использования классов case - получать equals и hashCode (и некоторые другие вещи) бесплатно. Если вы все равно будете переопределять все это, объявляйте его как класс case, просто запутывающим и не имеющим никакой пользы.

Смежные вопросы