Решил обзорно познакомиться с Ruby как с одним из основных конкурентов Python и наткнулся на вот такую интересную конструкцию:
class File
def File.open_and_process(*args)
f = File.open(*args)
yield f
f.close()
end
end
File.open_and_process("file", "r") do |file|
while line = file.gets
puts line
end
end
Создатели класса File практически (исключения я в данной ситуации не рассматриваю) гарантированно освобождают захваченные ресурсы, позволив пользователю класса не задумывать об этом. Или, что еще важнее, освобождение ресурса никак не зависит от памяти и внимательности пользователя класса.
Но это Ruby, а как в других языках программирования подходят к решению данной задачи?
- С неуправляемыми ООП языками (С++) все понятно – там есть деструкторы, в которых можно освободить все захваченные ресурсы.
- В неком абстрактном ООП языке программирования можно использовать следующий подход. Реализовать базовый класс:
Base(object):
private file;
public work_with_file(file):
pass
public run():
file = openfile()
work_with_file(file)
close_file(file)
А пользователя, в свою очередь, заставить создавать от него наследников, реализующих определённую работу с ресурсом:
First(Base):
public work_with_file(file):
// do some work with file
Но, требовать наследования в данном случае мне кажется чрезмерным и нецелесообразным.
- В Python можно использовать ключевое слово with, но в этом случае мы не застрахованы от того, что пользователь нашего класса однажды не использует его без with.
- Пожалуй самым удачным и универсальным решением является передача функции (callback), осуществляющую работу с ресурсом в класс, ответственный за захват и освобождение ресурса. На Python это будет выглядеть так:
def withResource(f):
resource = open('decor1.py')
try:
f(resource)
finally:
resource.close()
def readlines(resource):
for line in resource:
print line
withResource(readlines)
В С++ в данном случае можно воспользоваться указателем на функцию, как параметром метода класса, работающего с ресурсом.
Обсуждение на RSDN c примерами кода на Haskell, Scala, Lua, SML.