Search code examples
resourcesinstancecrystal-lang

Is there a way to redefine/disable self.new?


I'm trying to figure out a way to safely free resources acquired by a class. I tried using finalize, but it's unreliable. Sometimes I close my program before GC has a chance to free resources.

So I decided to use class instance in a block like this:

class Foo

  def destroy # free resources
      #...
  end

  #...

  def self.create(*args)
      instance = self.new(*args)
      begin
        yield instance
      ensure
        instance.destroy
      end
end

Foo.create do |foo|
  # use foo
end

That works fine, but I still can create an instance using new that I'd have to destroy explicitly. I tried to write my own new but it seems like it's just overloaded by default new.

Is there a way to redefine\disable new?


Solution

  • That is initialize method, that should be made private:

    class Foo
      @foo : String
    
      private def initialize(@foo)
      end
    
      def destroy
        puts "Destroying #{self}"
      end
    
      def self.create(arg)
        instance = new(arg)
        yield instance
      ensure
        instance.destroy if instance
      end
    end
    
    Foo.create("bar") do |foo| # will work
      p foo
    end
    
    Foo.new("bar")             # will raise
    

    Playground