Reputation: 5617
Have been observing some unexpected behavior when a class
region appears in another class definition:
Such region overrides whole class definition there.
However, the same code will just add new method to this class, as shown in codes below.
Why is Ruby designed like this, if it isn't a little beyond intuition?
require 'pp'
def pp_methods obj
pp obj.methods - nil.methods
end
#first definition of A
class A
def method1
end
end
#add method3 to A
class A
def method3
end
end
class B
#class A got overridden within class B
class A
def method2
end
end
def initialize
a=A.new
pp_methods a # => [:method2]
end
end
a1=A.new
pp_methods a1 # => [:method1,:method3]
b=B.new
a2=A.new
pp_methods a1 # => [:method1,:method3]
pp_methods a2 # => [:method1,:method3]
Upvotes: 0
Views: 42
Reputation: 96934
Being able to "reopen" classes is actually very useful. By having this ability we can easily add functionality to existing libraries, or fix issues ("monkey-patch"), without having to modify the actual library code. A contrived example:
class String
def foo
"bar!"
end
end
"hello".foo # => "bar!"
As for the second case, that A
is actually B::A
, which is entirely different than A
, and thus not reopening your initial A
. We can see this here:
class A
end
A # => A
class B
end
B # => B
B::A # warning: toplevel constant A referenced by B::A
# => A
class B
class A
end
end
B::A # => B::A
A.object_id # => 70359576062780
B::A.object_id # => 70359575976320
Upvotes: 3