Я работал с книгой «Программирование на Scala» и был поражен небольшой проблемой в реализации класса Rational
в главе 6.
Это моя начальная версия класса Rational
(по книге)
class Rational(numerator: Int, denominator: Int) {
require(denominator != 0)
private val g = gcd(numerator.abs, denominator.abs)
val numer = numerator / g
val denom = denominator / g
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int =
if(b == 0) a else gcd(b, a % b)
// other methods go here, neither access g
}
Проблема здесь в том, что поле g остается в течение всего времени существования класса, даже если к нему больше не обращаются. Эту проблему можно увидеть, запустив следующую фиктивную программу:
object Test extends Application {
val a = new Rational(1, 2)
val fields = a.getClass.getDeclaredFields
for(field <- fields) {
println("Field name: " + field.getName)
field.setAccessible(true)
println(field.get(a) + "\n")
}
}
Его результат будет:
Field: denom
2
Field: numer
1
Field: g
1
Решение, которое я нашел на Scala Wiki, включает следующее:
class Rational(numerator: Int, denominator: Int) {
require(denominator != 0)
val (numer, denom) = {
val g = gcd(numerator.abs, denominator.abs)
(numerator / g, denominator / g)
}
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int =
if(b == 0) a else gcd(b, a % b)
// other methods go here
}
Здесь поле g является локальным только для своего блока, но, запустив небольшое тестовое приложение, я нашел другое поле x$1
, в котором хранится копия кортежа, состоящего из (numer, denom)
!
Field: denom
2
Field: numer
1
Field: x$1
(1,2)
Есть ли способ построить рациональное выражение в Scala с помощью вышеуказанного алгоритма, не вызывая утечек памяти?
Спасибо,
Флавиу Сипциган
denom
иnumer
действительно ценности? Я бы совсем не удивился, если бы это были только методы доступа формыdef denom = x$1._2
. - person Raphael   schedule 31.08.2011