2011-05-02 2 views
0

Приведенные ниже код генерирует:
хэш-код зовут
хэш-код зовут
Имени равняется
ID = 0множественные inherance, наборы и хэш-код/​​равен главной

import scala.collection.mutable 
object TestTraits { 
    def main(args: Array[String]): Unit = { 
    val toto0 = new Person(0,"toto") 
    val toto1 = new Person(1,"toto") 
    val peoples = mutable.Set.empty[PersonID] 
    peoples.add(toto0) 
    peoples.add(toto1) 
    peoples.foreach(_.showID) 
    //peoples.foreach(_.saySomething)//won't compile' 
    } 
} 

trait Name{ 
    var theName="" 
    override def hashCode(): Int = { 
    println("Name's hashCode") 
    var hash = 5; 
    hash = 71 * hash + this.theName.##; 
    hash 
    //super.hashCode()//infinite loop 
    } 

    override def equals(that: Any): Boolean = { 
    println("Name's equals") 
    that match { 
    case that: Name  => this.theName.equals(that.theName) 
    case _ => false 
    } 
    } 
} 

abstract class PersonID{ 
    val idNumber: Int 

    override def hashCode(): Int = { 
    println("PersonID's hashCode") 
    super.## 
    } 
    override def equals(that: Any): Boolean = { 
    println("PersonID's equals") 
    that match { 
    case that: PersonID  => this.eq(that) 
    case _ => false 
    } 
    } 
    def showID: Unit = { 
    println("ID=" + idNumber) 
    } 
} 

class Person(val id:Int, val s:String) extends { 
    val idNumber=id 
} with PersonID with Name { 
    /*override def hashCode(): Int = { 
    println("Person's hashCode") 
    super.## //infinite loop !! 
    } 
    override def equals(that: Any): Boolean = { 
    println("Person's equals") 
    that match { 
    case that: Person  => this.eq(that) 
    case _ => false 
    } 
    }*/ 
    theName=s 
    def saySomething: Unit = { 
    print("Hello, my name is " + theName + ", ") 
    showID 
    } 
} 

Так как "народы" представляет собой набор PersonId , Я ожидал следующий результат:
Персональный код hashCode
Персональный идентификатор hashCode
ID = 0
ID = 1

Может ли кто-нибудь объяснить это поведение и как сделать то, что я ожидал (т. Е. Иметь класс с «равными» на основе значений полей, кроме случаев, когда экземпляр помещается в Set [PersonID])

Другая загадка - почему я получаю бесконечные циклы, когда использую super.hashCode() в своем обычном хэш-коде?

PS: Я использую предварительно инициализированный абстрактный элемент, потому что мне нужно это в моем реальной пользе деле ...

ответ

1

я получаю вместо этого:

Name's hashCode 
Name's hashCode 
Name's equals 
ID=0 

Это происходит потому, что Name последняя черта инициализация, поэтому это переопределения hashCode и equals будет первым, кто будет называться. Вы хотели, чтобы Set вызывал методы, основанные на статическом типе (т. Е. То, что было объявлено), что не так, как работает OO. Если бы это было так, наследование и переопределение были бы почти бесполезны.

Что касается того, как выполнить то, что вы хотите ... вы не можете. Было бы неплохо, если бы был Set, который взял класс типа Equal[A], но его нет. Может быть, у Скалаза это есть.

Кстати, есть звонок super.##, который считается незаконным на Scala 2.9.0.rc2. Я не уверен, что это значит.

+0

Спасибо за ваш ответ, теперь ясно, что я должен реализовать это по-другому. – acapola

1

Другая загадка - почему я получаю бесконечные циклы, когда использую super.hashCode() в своем обычном хэш-коде?

Внешняя часть чисел в штучной упаковке, вся реализация ## - вызов hashCode.

В вашей реализации hashCode вы вызываете (или пытаетесь позвонить) ##.

Тайна решена!

+0

Я думаю, что рекурсия не должна происходить, поскольку я намеревался вызвать super.hashCode(), а не this.hashCode(). Как и вы, я думал, что hashCode и ## действительно являются одним и тем же методом, но после изменения ## по hashCode() бесконечный цикл исчезает ... – acapola

+0

Я почти уверен, как это работает, поскольку я написал его. ## вызывает hashCode. Я не уверен, какая часть этого вам непонятна, или я уточню дальше. – extempore

+0

Непонятно, что я получаю бесконечный цикл, несмотря на вызов super. ##. Другой парень на форуме scala дал мне следующее объяснение: «Ваши бесконечные циклы вызваны использованием супер. ## из определения метода hashCode. Вызов x. ## будет переводить на вызов ScalaRunTime.hash (x), который, в свою очередь, для потомка AnyRef, вызовет x.hashCode(). Использование super здесь вам не поможет. Если вы используете super.hashCode(), тогда вы получите поведение, которое, как вам кажется, ожидает ». – acapola

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