When is #finalize run?


#1

I wrote up this example, to see if a finalizer goes away when a class is inherited, but the finalizer doesn’t seem to be called at any point. When is a finalize method called?

class Parent
  property parent_prop = "Parent property"

  def initialize
    puts "initializing parent"
  end
  def initialize(@parent_prop)
  	puts "initializing parent"
  end
	def finalize
    puts "Finalizing parent!"
  end
end

class Child < Parent
  property child_prop = "Child property"
  
  def initialize
    puts "initializing child"
  end
end

p! (p = Parent.new), (p = nil), (c = Child.new), (c = nil)

sleep 15
puts "collecting"
100.times { GC.collect }
puts "done"

output:

(p = Parent.new) # => initializing parent
#<Parent:0x102d20f20 @parent_prop="Parent property">
(p = nil)        # => nil
(c = Child.new)  # => initializing child
#<Child:0x102d20f00 @parent_prop="Parent property", @child_prop="Child property">
(c = nil)        # => nil
collecting
done

#2

Try this:

p = Parent.new
p = nil
c = Child.new
c = nil

puts "collecting"
GC.collect
puts "done"

The p! macro creates temporary variables to hold each of the expressions. That means they will still be in the stack when you call GC.collect.


#3

Actually, what I said is not correct… but I’m sure some things remain in the stack, for some reason. I’ll need to debug it, but I don’t consider this something super important. The GC will collect things when they are unreachable: no references in the heap or stack. And you shouldn’t rely on GC.collect to collect things you don’t need anymore.


#4

My use of GC.collect was just to try to get the #finalize method to be called. I suppose my real question is whether the #finalize method of a superclass goes away along with all of the initialize methods when an initialize method is overridden in a subclass, or if perhaps a #finalize method is never inherited… some strange behavior like that.

To be specific, I’m writing a shard and CLI for converting between different subtitle file-formats. I wanted a superclass Format with a @content property which could be any IO including an open file, and I wanted to make sure that this method would make it into the subclasses and not just be a part of the (abstract) superclass.

def finalize
  @content.close if @content.responds_to? :close
end

Thanks @asterite


#5

Yes, finalize is (or should) be inherited.


#6

Thank you!