Time
Inherit Classes From Struct

I’ve recently spotted a curious trend in blogposts about Ruby. It’s the way people define classes in examples. It goes like this:

class Foo < Struct.new(:bar)
  # some methods...
end

Why? Because it’s shorter replacement for this:

class Foo
  attr_accessor :bar
  
  def initialize(bar)
    @bar = bar
  end
end

The other way to save typing on attributes lookes like this:

Foo = Struct.new(:bar) do
  # some methods...
end

It brought up an interesting discussion on twitter, when @jeg2 said he didn’t like the practice. One important consequence of using it that was mentioned in this discussion is changing of ancestor chain.

When declaring class usual way:

Foo.ancestors
=> [Foo, Object, Kernel, BasicObject]

When inheriting from Struct.new:

Foo.ancestors
=> [Foo, #<Class:0x00000001d41100>, Struct, Enumerable, Object, Kernel, BasicObject]

When creating a constant from Struct.new:

Foo.ancestors
=> [Foo, Struct, Enumerable, Object, Kernel, BasicObject]

Have you noticed Enumerable in two later cases? It means that suddenly instances of your class start to respond to each method and a bunch of other methods. So it’s better be careful using Struct like this.