Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active August 29, 2015 14:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/cf7f587258cc721755d6 to your computer and use it in GitHub Desktop.
Save JoshCheek/cf7f587258cc721755d6 to your computer and use it in GitHub Desktop.
require 'objspace'
class A
# When we include a module, it makes an invisible "included class" (T_ICLASS),
# and places it in the inheritance hierarchy, as the superclass.
# Hence A the inclusion, A no longer has a direct reference to Object,
# it now has a direct reference to the included class
ObjectSpace.reachable_objects_from(self) # => [#<InternalObject:0x007f8cd29343b8 T_CLASS>, "A", Object]
m = Module.new
include m
ObjectSpace.reachable_objects_from(self) # => [#<InternalObject:0x007f8cd29343b8 T_CLASS>, "A", #<InternalObject:0x007f8cd2934020 T_ICLASS>]
# The included class keeps a reference to the module, thus when we ask for things like .ancestors,
# it gives us the module instead of the included class. This is seen as an implementation detail.
A.ancestors # => [A, #<Module:0x007f8cd2934048>, Object, PP::ObjectMixin, Kernel, BasicObject]
# It must go through the included class to access Object, or the module
iclass = ObjectSpace.reachable_objects_from(self).last
iclass # => #<InternalObject:0x007f8cd2934020 T_ICLASS>
ObjectSpace.reachable_objects_from(iclass) # => [#<Module:0x007f8cd2934048>, "#<Module:0x007f8cd2934048>", Object]
# The module does not have a name until it is assigned to a constant.
# But even then, that name is not generated until it is asked for.
Object.const_set(:M, m)
ObjectSpace.reachable_objects_from(iclass) # => [M, "#<Module:0x007f8cd2934048>", Object]
m.name # => "M"
ObjectSpace.reachable_objects_from(iclass) # => [M, "M", Object]
end
require 'objspace'
# When we define our first singleton method, that creates a new class to house the method,
# and places the class it at the object's class pointer.
# This means the object has no direct reference to its original class, it must go through the superclass.
# This also explains how every object can have a singleton class: they are created lazily
o = Object.new
ObjectSpace.reachable_objects_from(o) # => [Object]
def o.zomg; end
ObjectSpace.reachable_objects_from(o) # => [#<InternalObject:0x007ffb94814c90 T_CLASS>]
sclass = ObjectSpace.reachable_objects_from(o).first
ObjectSpace._id2ref(sclass.internal_object_id) # => #<Class:#<Object:0x007ffb94814f60>>
o.singleton_class # => #<Class:#<Object:0x007ffb94814f60>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment