Written August 18, 2013. Tagged Ruby.
String as a shortcut for classes that initialize with strings isn't necessarily a great idea.
I've seen it used most recently to define a
DNA class on exercism.io, e.g.
class DNA < String
dna = DNA.new("GATTACA")
dna.to_rna # => "GAUUACA"
This is often misguided for much the same reasons that inheriting from
Your subclass will happily do this:
dna = DNA.new
Struct inheritance, a missing argument won't cause a method like
#to_rna to explode with
nil errors, as
self will still be an empty string. Instead of exceptions you risk unexpected behavior, like empty strands of DNA kicking around your application. Exploding would be preferable.
String you suggest that
DNA is a specialized string.
It will get a ton of methods in its API, such as
#each_line. Do those make sense for your class?
DNA class above, it's impossible to tell what subset of methods you intended to inherit and think make sense for this class. Only the initializer? Also
#to_s? You should only inherit a class when all its methods make sense for the subclass.
If it's the initializer you want, just write your own or use some library to reduce boilerplate. If it's some other method, delegate those to a string – composition instead of inheritance. It will make the API of your class clearer.
DNA, it's probably reasonable that
DNA.new("GATTACA") == DNA.new("GATTACA"). If that's not how you want identity to work, though, be aware that your class will inherit this behavior.
Steve Klabnik mentions some gotchas of inheriting a core class like
#to_s is not called implicitly with interpolation. Your initializer won't always be called.
You won't trigger these gotchas most of the time, but some time you might, and it's easily avoided by not inheriting from