문제

나는 당신이 물체가 파괴 될 때 일어나는 일을 제어 할 수 없다는 것이 디자인으로 알고 있습니다. 또한 일부 클래스 메소드를 파이널 라이저로 정의한다는 것을 알고 있습니다.

그러나 C ++의 RAII에 대한 Ruby 관용구 (자원은 생성자에서 초기화되고 소멸자에서 닫힙니다)입니까? 사람들은 오류 나 예외가 발생하더라도 객체 내부에서 사용되는 자원을 어떻게 관리합니까?

사용 보장하다 공장:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

그러나 수업의 사용자 전체 시작 구속기 chacha를해야한다는 것을 기억해야합니다 열린 방법을 호출해야 할 때마다.

예를 들어, 다음 수업을받을 것입니다.

class SomeResource
 def initialize(connection_string)
   @resource_handle = ...some mojo here...
 end

 def do_something()
   begin
    @resource_handle.do_that()
    ...
   rescue
    ...
   ensure
 end

 def close
  @resource_handle.close
 end

end

다른 클래스의 예외가 원인이되고 스크립트가 종료되면 resource_handle은 닫히지 않습니다.

아니면 내가 아직도 이것을하고있는 문제는 C ++처럼?

도움이 되었습니까?

해결책

그래서 사용자는 "전체 시작 구속기 chacha를해야한다는 것을 기억해야합니다" 결합시키다 rescue/ensure ~와 함께 yield.

class SomeResource
  ...
  def SomeResource.use(*resource_args)
    # create resource
    resource = SomeResource.new(*resource_args) # pass args direct to constructor
    # export it
    yield resource
  rescue
    # known error processing
    ...
  ensure
    # close up when done even if unhandled exception thrown from block
    resource.close
  end
  ...
end

클라이언트 코드는 다음과 같이 사용할 수 있습니다.

SomeResource.use(connection_string) do | resource |
  resource.do_something
  ... # whatever else
end
# after this point resource has been .close()d

사실 이것은 방법입니다 File.open 운영 - 첫 번째 답변을 최대한 혼란스럽게합니다 (글쎄 나의 직장 동료).

File.open("testfile") do |f|
  # .. process - may include throwing exceptions
end
# f is guaranteed closed after this point even if exceptions are 
# thrown during processing

다른 팁

어때 yield블록에 리소스를 구입 하시겠습니까? 예시:

File.open("testfile") do |f|
  begin
    # .. process
  rescue
    # .. handle error
  end
end

아니면 내가 아직도 이것을하고있는 문제는 C ++처럼?

예, C ++ 리소스 거래는 스택의 모든 것에 대해 암시 적으로 발생하기 때문에입니다. Stack Unound = Resource Destroyed = Destructors 호출 및 거기에서 물건을 해제 할 수 있습니다. 루비에는 소멸자가 없기 때문에 "다른 모든 것이 완료되면"그 자리가있는 곳에서 몇 번의 사이클을 지연시킬 수 있기 때문에 "다른 모든 일이 완료되면"아무것도 없습니다. 당신은 최종화기를 가지고 있지만 "림보"라고 불립니다 (모든 것이 사용 가능하지는 않습니다). GC에서 호출됩니다.

따라서 더 나은 릴리스 자원에 대한 핸들을 보유하고 있다면 명시 적으로 해제해야합니다. 실제로 이런 종류의 상황을 처리하는 올바른 관용구는

def with_shmoo
  handle = allocate_shmoo
  yield(handle)
ensure
  handle.close
end

보다 http://www.rubycentral.com/pickaxe/tut_exceptions.html

Ruby에서는 An을 사용할 것입니다 ensure 성명:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

이는 Python, Java 또는 C# 사용자에게 Try / Catch / Minall과 같은 작동한다는 점에서 친숙합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top