On ruby, what is the reason for include
is private, while Object#extend
is public?

- 78,473
- 57
- 200
- 338

- 8,464
- 3
- 41
- 58
3 Answers
Object#extend
has to be public, otherwise you wouldn't be able to use it. After all, its purpose is to mix in a module into an object, so you'd generally call it like obj.extend(Foo)
, which isn't possible with private methods.
Module#include
is usually only used inside a module body like so:
class Bar
include Foo
end
I.e. it is usually called without a receiver, so it doesn't have to be public. Of course, it doesn't have to be private either.
My guess is the reason why it is private is that it is more invasive, because it changes the behavior of every instance of Bar
, whereas Object#extend
only changes a single object. Therefore, Module#include
is in some sense "more dangerous" and thus is made private.
I don't know whether that is the actual reason, but it is consistent with other similar methods like Module#define_method
.

- 363,080
- 75
- 446
- 653
-
It doesn't *have* to be. You would be able to use it if it was private: `obj.send(:extend, Foo)`, `obj.instance_eval{ extend Foo }`, not including the case for modules `class Bar; extend Foo; end` – Marc-André Lafortune Jun 02 '12 at 20:39
-
@Marc-AndréLafortune: Or `class << obj; extend Foo; end`, of course. Like I said, it's just a guess. – Jörg W Mittag Jun 02 '12 at 22:26
-
I was replying to your first sentence "`Object#extend` has to be public, otherwise you wouldn't be able to use it." – Marc-André Lafortune Jun 02 '12 at 23:43
-
PS: I can't think of a single circumstance where one would do `class << obj; extend Foo; end`, as in your comment. – Marc-André Lafortune Jun 06 '12 at 01:18
-
5Fast-forward to 2014. `Module#include` (and `Module#prepend`) were made public in v2.1. – Cary Swoveland Mar 23 '15 at 11:44
To be able to run Foo.include(Bar)
at any point would most likely be a source of very nasty bugs.

- 131,503
- 21
- 160
- 205
To supplement Jörg W Mittag's answer, Object#extend can also be used to include module's instance methods to be used in the class level (which will also be available to all instances of that class):
module Foo
def bar (baz)
end
end
class Qux
extend Foo
bar 'asdf'
end

- 1,055
- 1
- 11
- 26