Reputation: 680
I came across this error while in development.
class ABC
def self.method_1
method_2
p "method_1"
end
private
def method_2
p "method_2"
end
end
ABC.method_1 # `method_1': undefined local variable or method `method_2' for ABC:Class (NameError)
But if I do it like this, then it works
def self.method_1
method_2
p "method_1"
end
def self.method_2
p "method_2"
end
private_class_method :method_2
end
ABC.method_1
Please help me in understanding this.
Upvotes: 0
Views: 54
Reputation: 1286
@Jorg's answer is correct, but this might be easier to read. As Jorg pointed out, the use of the "self" applies to the class object, not the specific instance of it. basically mixing and matching the "self" and not-"self" entries is hard work, and you shouldn't try to cross the streams. the "self" and non-"self" objects will act as completely different classes.
class
class ABC
def method_1
method_2
p "method_1"
end
def self.method_3
method_4
p "method_3"
end
private
def method_2
p "method_2"
end
def self.method_4
p "method_4"
end
end
output
> ABC.new.method_1
"method_2"
"method_1"
=> "method_1"
> ABC.method_3
"method_4"
"method_3"
=> "method_3"
Upvotes: 1
Reputation: 369428
In Ruby, the default implicit receiver of a message send, if you do not explicitly specify a receiver, is self
.
Also, the default definee of a method definition expression, if you do not explicitly define a definee, is the closest lexically enclosing module definition.
In your first example, method1
is defined with an explicit definee of self
, which at that point in the execution is the class ABC
itself. This means that method1
is a class method of class ABC
, which is actually just a singleton method of ABC
, which in turn is just an instance method of ABC
's singleton class.
method2
is defined without an explicit definee, which means it will be defined on the default definee. The closest lexically enclosing class or module definition in this case is the class definition of ABC
, so method2
is defined as an instance method of ABC
.
In other words: method1
and method2
are defined in two completely different classes.
Now, when you call ABC.method1
, you are sending the message method1
to the explicit receiver ABC
. This works, because method1
is found in ABC
's singleton class.
Inside of method1
, you are calling method2
without an explicit receiver. That means, the message is sent to the implicit receiver self
, which is ABC
in this case. So, it is roughly equivalent (module access restrictions) to ABC.method2
.
BUT there is no definition of method2
in either the singleton class of ABC
er the class of ABC
(which is Class
) or any of its superclasses (Module
, Object
, Kernel
, BasicObject
) because method2
is defined in ABC
itself.
Therefore, method2
cannot be found in the method lookup chain.
In the second example, both methods are defined in the same class, namely both methods are defined in ABC
's singleton class. Therefore, method2
is in the method lookup chain when called inside of method1
.
In fact, your first example is actually not substantially different from this:
class Foo
def method 1
method2
end
end
class Bar
def method2; end
end
foo = Foo.new
foo.method1
Upvotes: 2