2015-11-06 5 views
0

Я новичок в Scala и запутался в смешивании признаков. Я использую несколько черт для хранения некоторой группы полей и смешиваю их с конкретным классом.Сбои с «родительскими» полями в equals/hashCode конкретного класса (или класса case), который расширяет многозначные черты (с конкретными полями)

Глобальный вопрос о том, как методы equals и hashCode будут использовать эти поля (поля в чертах могут иметь значения по умолчанию).

На самом деле, я не планирую иметь кучу бизнес-структур и снова определять все эти поля. Мой класс может иметь множество комбинаций полей, и я хочу использовать шаблон Builder или цепочку простых мутаторов. Я не понимаю, как я могу управлять полями из разных черт в своих равных и хэш-кодах конкретного класса (я могу с ними только жестко кодировать логику, но не могу использовать «super.equals()»). Черты не могут иметь свои собственные методы equals/hashCode, или я ошибаюсь в какой-то момент?

Пример:

trait Task { 

    var name: Option[String] = None 

    var comment: Option[String] = None 

    ... // plenty other fields 

} 

trait Budget { 

    var price: Option[Long] = None 

} 

class Event extends Task with Budget { 

    var place: Option[String] = None 

    ... // plenty other fields 

} 

При использовании тематических классов вместо - сгенерированные равно/хэш-код/​​ToString не работают родительские поля (поля из признаков)

+0

Я провел неделю пытается получить использование «смешивания» концепции в Scala, и теперь я пришел к мысли, что простой «Композиция» по-прежнему отличный способ для достижения своей цели – maret

+0

Состав почти всегда предпочтительнее укладывать стек. Так что иди с этим! –

+0

ОК, я, хотя это в Scala это правило было пересмотрено из-за черт – maret

ответ

3

Почему нет. Вы можете легко overrideequals и hashCode в любых целях, которые вам нравятся.

trait PP { 
    override def hashCode(): Int = 1 

    override def equals(obj: scala.Any): Boolean = true 
} 

class BB(val z: Int) extends PP { 
    override def hashCode(): Int = super.hashCode() 

    override def equals(obj: Any): Boolean = super.equals(obj) && (obj match { 
    case b: BB => b.z == z 
    case _ => false 
    }) 
} 

Определенно, вы должны быть очень осторожны с хэш-кодом и равны реализацией в этих признаках (в то время как сделать проверку типа: obj.isInstanceOf[otherTrait]) соблюдать контракт этих методов.

-

Sample доказать все equals вызываются.

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

    trait T1 { 
    override def equals(obj: scala.Any): Boolean = { 
     println("T1 invoked") 
     super.equals(obj) 
    } 
    } 

    trait T2 { 
    override def equals(obj: scala.Any): Boolean = { 
     println("T2 invoked") 
     super.equals(obj) 
    } 
    } 
    trait T3 extends T1 { 
    override def equals(obj: scala.Any): Boolean = { 
     println("T3 invoked") 
     super.equals(obj) 
    } 
    } 
    class C1 extends T1 with T2 with T3 { 
    override def equals(obj: scala.Any): Boolean = { 
     println("C1 invoked") 
     super.equals(obj) 
    } 
    } 

    new C1().equals(new C1()) 

// Exiting paste mode, now interpreting. 

C1 invoked 
T3 invoked 
T2 invoked 
T1 invoked 
defined trait T1 
defined trait T2 
defined trait T3 
defined class C1 
res7: Boolean = false 

scala> 

scala> 
+0

Убедитесь, что вы правильно выполнили все методы 'equals'. Они ожидали называть «супер» повсюду. – Rumoku

+0

Смотрите мой новый образец. – Rumoku

+1

Да! Это он ... Я забыл назвать супер во всех чертах. – maret

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

  • Нет связанных вопросов^_^