Skip to content

Instantly share code, notes, and snippets.

@JEG2
Created July 25, 2013 02:53
Show Gist options
  • Save JEG2/6076534 to your computer and use it in GitHub Desktop.
Save JEG2/6076534 to your computer and use it in GitHub Desktop.
My thoughts on inheriting from Ruby's base types.

I've been in multiple discussions lately about the problems with subclassing Ruby's base types.

The main problem is that Ruby sometimes takes shortcuts with the base types, for performance reasons. This can cause them to behave odd. For example, have a look at this subclass:

class MyString < String
  def initialize(*)
    super
    puts "Building MyString:  #{inspect}"
  end
end

result = MyString.new("CATG").tr(MyString.new("T"), MyString.new("U"))
p result.class
p result

That outputs the following

Building MyString:  "CATG"
Building MyString:  "T"
Building MyString:  "U"
MyString
"CAUG"

Notice that the constructor was not called for the fourth MyString returned as a result from the tr() call.

Reopening String itself can lead to even more surprising behavior:

class String
  alias_method :string_initialize, :initialize

  def initialize(*args, &block)
    string_initialize(*args, &block)
    puts "Building MyString:  #{inspect}"
  end
end

result = String.new("CATG").tr("T", "U")
p result.class
p result

This works even less often:

Building MyString:  "CATG"
String
"CAUG"

You can see that it only works with the explicit call. Ruby's syntactic shortcuts just bypass the constructor altogether.

My opinion is that these inconsistencies mean that this tactic is just best avoided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment