Как написать деструктор класса в Scala? - PullRequest
12 голосов
/ 23 октября 2010

Я бы хотел, чтобы FileWriter открывался в течение всего времени существования экземпляра класса. Поэтому мне нужно закрыть его в деструкторе. Но как указать деструктор в Scala?

Ответы [ 4 ]

10 голосов
/ 23 октября 2010

Возможно, вам будет интересно ознакомиться с проектом scala-arm Джоша Суерета, который обеспечивает как монадическое, так и основанное на разделении управление ресурсами только для этого источника использования: http://github.com/jsuereth/scala-arm

Если вы действительно думаете, что вынужен деструктор (т. е. потому что вы думаете, что вам нужно создать объект, а затем передать его и больше никогда его не видеть). Я бы рекомендовал вместо этого пересмотреть архитектуру вашего приложения ... просто нет способа сделать эту работу надежной в JVM.

8 голосов
/ 31 октября 2012

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

def closer [T, C <: Closeable] (c : C) (f : C => T) : T = 
    try f (c)
    finally c.close

Использовать его очень просто. В приведенном ниже примере используется входной поток из URLConnection. Конечно, вместо connection.getInputStream вы можете создать любой произвольный поток (или, в более общем случае, любой произвольный закрываемый объект).

val bytes = closer (connection.getInputStream) { istream =>
        val bytes = new ByteArrayOutputStream ()
        val buffer : Array [Byte] = new Array (1024)
        Iterator.continually (istream read buffer).takeWhile (_ > 0).foreach (bytes write (buffer, 0, _))
        bytes.toByteArray
    }

Эта версия будет работать с любым методом close (не нужно реализовывать Closeable или что-либо еще).

def autoClose[R <: {def close()}, T](resource: R)(use: R => T): T = {
  try use(resource)
  // Don't want an NPE here masking an exception from use.
  finally Option(resource).foreach(_.close())
}

Вот некоторые неявные классы для выполнения этой работы.

implicit class AutoCloseBracket[R <: Closeable](resource: R) {
  def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
implicit class AutoCloseableBracket[R <: AutoCloseable](resource: R) {
  def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
7 голосов
/ 23 октября 2010

Скала не имеет деструкторов. У него есть финализаторы, такие как Java, но они совсем не одно и то же. Также есть интересная серия блогов по эмуляции ключевого слова C # using в Scala здесь:

2 голосов
/ 23 октября 2010

Как я отмечал выше, Java имеет существующий интерфейс Closeable специально для ввода-вывода, который вы можете использовать.Это не дает никакого сахара, но поможет людям правильно использовать ваш класс.

В Java 7 Closeable будет подинтерфейсом AutoCloseable.AutoCloseable - это более общий интерфейс для любого ресурса, который должен быть закрыт после использования, в то же время потенциально вызывая исключение.это часть запланированной поддержки Automatic Resource Management в Java 7. Менее значимой для вашего вопроса (поскольку вы используете Scala), также должен быть новый синтаксис Java (расширение существующих блоков try) для этого сценария.

...