P
Pit Capitain
7stud said:(...)
If I run the following code, I don't get any errors:
class MegaGreeter
attr_accessor :names
#constructor
def initialize(names = "world")
@names = names
end
#functions:
def say_hi
if @names.nil?
puts "..."
elseif @names.respond_to?("each")
@names.each do |name|
puts "Hello #{name}!"
end
else
puts "Hello #{@names}!"
end
end
end
if __FILE__ == $0
mg = MegaGreeter.new(["Sally", "Jane", "Bob"])
mg.say_hi
end
Hi 7stud,
when reading (compiling) your code, Ruby can only detect syntactic
errors, and your code is syntactically correct. Other errors can only be
determined at run time. Let me show you...
You get an error when you try your code with another instance:
mg2 = MegaGreeter.new(nil)
mg2.say_hi
Output:
...
in `say_hi': undefined method `elseif' (NoMethodError)
This error message shows that Ruby tried to execute the method #elseif,
which obviously isn't defined. Ruby cannot decide in advance whether
there will be an error or not:
mg3 = MegaGreeter.new(nil)
def mg3.elseif(arg)
puts "Hello from elseif with arg #{arg}"
end
mg3.say_hi
This code defines the method #elseif for the object mg3. The output is:
...
Hello from elseif with arg false
in `say_hi': undefined method `each' for nil:NilClass (NoMethodError)
You can see that the #elseif method is called, but then there's an error
in the next line: because @names is nil in this case, we call the method
#each on the object nil, which isn't defined.
I should have said: normally it isn't defined. We can change this:
def nil.each
yield "nil"
end
mg3.say_hi
This code defines the method #each for the object nil, so that it passes
the string "nil" to the block. The output is:
...
Hello from elseif with arg true
Hello nil!
You can see that your code executes fine in this case. This can only be
determined by actually running the code. Ruby is very dynamic, which
sometimes isn't an advantage, as has been in your case. But it can be a
very powerful tool, which is why we all hang out here.
Regards,
Pit