1

Looking through the sourcecode of the redis-store RubyGem, I stumbled upon this syntax I hadn't seen before:

class Foo < self
  # ...
end

My Google-Fu apparently isn't powerful enough, because I've been able to find nothing that describes what this does.

What I'm guessing this does, is somehow reopening Foo, extending it with itself as superclass, thereby making it possible to override methods that can call the original definition as super. Am I close?

KaptajnKold
  • 10,638
  • 10
  • 41
  • 56

2 Answers2

6
class Foo < Bar
end

Is how you tell Ruby that Foo inherits from Bar.

Within a class definition, self refers to the class itself:

# prints Foo
class Foo
  puts self
end

So

class Foo
  class Bar < self
  end
end

Just says that Bar is nested under Foo and it inherits from it.

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
  • Nitpick: `Bar` is *not* nested under `Foo`. There is no such thing as nested classes in Ruby. The *constant* `Bar` is defined inside the class `Foo`, but there *is no relationship whatsoever* between the *class* `Bar` and the *class* `Foo`. (Well, except for the fact that `Bar` inherits from `Foo`, but I am referring to the more general case of `class Foo < Qux; class Bar < Garble; end end`.) There are *tons* of Ruby tutorials that talk about nested classes, and there are tons of questions in [tag:ruby] on [so] where people are confused because nested classes don't seems to work, and the … – Jörg W Mittag Nov 11 '19 at 21:21
  • … simple reason is that Ruby *doesn't have nested classes*, and we should simply never talk about them as if Ruby did have nested classes. – Jörg W Mittag Nov 11 '19 at 21:21
  • @JörgWMittag on the other hand, if `Bar` were not nested under `Foo`, we couldn't use `self` to refer to `Foo` ;-) – Stefan Nov 12 '19 at 08:35
  • @JörgWMittag is it fair to say that the constant `Bar` is nested under `Foo`, whereas the class `Bar` inherits from `Foo`? – ndnenkov Nov 12 '19 at 09:07
4

The main thing that you seem to be messing is just this: the superclass portion of a Ruby class definition is an arbitrary Ruby expression.

So, something like this is perfectly legal:

class Foo < if rand < 0.5 then Bar else Qux end end

Obviously, this doesn't make sense, but for example, in _why the lucky stiff's brilliant little web micro framework Camping, routes are defined like this:

class Edit < R '/post/(\d+)/edit'

and Migrations are defined like this:

class BlogInitialSchemaCreation < V 1.0

In ActiveRecord, migrations are defined like this:

class CreateProducts < ActiveRecord::Migration[5.0]

All of this simply uses the fact that whatever is to the right of the < in a class definition can by any arbitrary Ruby expression which is evaluated when the class definition is evaluated.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • I think the OP was under the impression that `self` in `class Foo < self` refers to the class itself, i.e. `Foo` instead of `Bar`. (hence _"with itself as superclass"_) – Stefan Nov 12 '19 at 08:51