Subclassing nil in Ruby 2.7.2 (the old version broke)
RUBY_VERSION # => "2.7.2" | |
require 'fiddle' | |
User = Struct.new :name | |
class NullUser < NilClass | |
# We have no way to allocate a new NullUser... BUT! We can hack around this | |
# by making a new object and setting its class pointer to point at NullUser | |
def self.new(*) | |
instance = Object.new | |
instance_ptr = Fiddle::Pointer.new Fiddle.dlwrap instance | |
klass_ptr = Fiddle::Pointer.new Fiddle.dlwrap self | |
instance.class # => Object | |
instance_ptr[8, 8] = klass_ptr.ref[0, 8] # set the new object's class | |
instance.class # => NullUser | |
instance | |
end | |
def name | |
'' | |
end | |
end | |
user = User.new 'Samantha' | |
user.name # => "Samantha" | |
user.to_h # => {:name=>"Samantha"} | |
user.nil? # => false | |
user # => #<struct User name="Samantha"> | |
user = NullUser.new | |
user.name # => "" | |
user.to_h # => {} | |
user.nil? # => true | |
user # => nil | |
# Just to prove the point: | |
def nil.omg? | |
:wtf | |
end | |
user.omg? # => :wtf | |
# One reason this works is b/c of this possible bug | |
# if they ever fix this, we'll have to do more work to hack around it. | |
nil.singleton_class.singleton_class? # => false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment