Reply to comment
An Example of Ruby Introspection
Now, let's create an instance of this class:
someone = Person.new
Suppose later in the program you want to see if the person has been named. Here is a way to do it:
if someone.name.empty?
puts "no name"
end
That's simple enough, but probably wrong.
The problem is that if the name property has not been initialized, its value is nil and the NilClass does not have an empty? method. In this case the code will fail with an error:
NoMethodError: undefined method `empty?' for nil:NilClass
So the safe way to do this is to check if the value is nil before you check if it is empty. Like so:
if someone.name.nil? || someone.name.empty?
puts "no name"
end
This is great, except it gets very tedious and can be error prone. Testing for nil is sort of like checking return codes for function failures: it's a good thing to do but it's easy to forget and it adds a lot of crud to your code. The solution for the return code problem is to use exceptions. The solution to the nil problem is to use the power of Ruby introspection to make a small change to the way the NilClass works.
Ruby, unlike Java, lays its entire guts out for you to use and modify. So, I can go into the NilClass and give it an empty? method that works in a reasonable fashion.
class NilClass
def empty?
true
end
end
What we are saying here is that something that is nil should also be considered empty. Seems reasonable enough. Best of all, with this change the first test case—without the explicit test for a nil value—now works without error.
Redefining basic language constructs in this way is generally a very bad thing to do. I believe, however, you can break the rules if done in a judicious and considered manner. This is one case where the change is so simple to understand and benefit is so great, I think it's worth doing.
Here is what Dave Thomas says in the Pickaxe book:
One of the many advantages of dynamic languages such as Ruby is the ability to introspect—to examine aspects of the program from within the program itself. Java, for one, calls this feature reflection but Ruby's capabilities go beyond Java's.
I'd be curious if the Ruby practitioners would agree my example is a good use of introspection? And if so, where is your line on modifying system constructs?
Trackbacks
Trackback URL for this post: http://www.unicom.com/trackback/412












