def moo
puts "moo"
end
moo.moo.moo.moo
this gives
moo
moo
moo
moo
just an oddity, I was curious if this was done on purpose and served some purpose...
self is a special variable that points to the object that "owns" the currently executing code. Ruby uses self everwhere: For instance variables: @myvar. For method and constant lookup. When defining methods, classes and modules.
self is a reserved keyword in Ruby that always refers to the current object and classes are also objects, but the object self refers to frequently changes based on the situation or context. So if you're in an instance, self refers to the instance. If you're in a class, self refers to that class.
Ruby doesn't really have functions. Rather, it has two slightly different concepts - methods and Procs (which are, as we have seen, simply what other languages call function objects, or functors). Both are blocks of code - methods are bound to Objects, and Procs are bound to the local variables in scope.
A method in Ruby is a set of expressions that returns a value. Within a method, you can organize your code into subroutines which can be easily invoked from other areas of their program. A method name must start a letter or a character with the eight-bit set.
I'm guessing you're doing that in console, so you're actually defining the method on the Object
, which then defines the method on all the children of Object
... which is everything. So your method:
def moo
puts "moo"
end
Returns nil
, and because you defined the method on Object
, NilClass
has the method as well, so you can call moo
on NilClass
.
If you do:
class Foo
def bar
1 + 1
end
end
And then:
f = Foo.new
f.bar.bar
You get:
NoMethodError: undefined method `bar' for 2:Fixnum
Perhaps you're defining something on the Object
class. Because everything in Ruby is an Object
and every method returns something (defaulting to nil
), you can call that method on its own result. The moo
method returns nil
, and so what you are doing is calling moo
first on the global object, and then on each nil
returned.
You can more explicitly do this:
class Object
def moo
puts 'moo'
end
end
If you generally want to chain methods, you could try this:
class Mooer
def moo
puts 'moo'
self
end
end
a = Mooer.new
a.moo.moo.moo.moo.inspect
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With