Now let’s create a greeter object and use it:
irb(main):035:0>greeter=Greeter.new("Pat")=> #<Greeter:0x16cac @name="Pat">irb(main):036:0>greeter.say_hiHi Pat!=>nilirb(main):037:0>greeter.say_byeBye Pat, come back soon.=>nilOnce thegreeter object is created, it remembers that the name is Pat. Hmm,what if we want to get at the name directly?
irb(main):038:0>greeter.@nameSyntaxError: (irb):38: syntax error, unexpected tIVAR, expecting '('Nope, can’t do it.
Instance variables are hidden away inside the object. They’re notterribly hidden, you see them whenever you inspect the object, and thereare other ways of accessing them, but Ruby uses the good object-orientedapproach of keeping data sort-of hidden away.
So what methods do exist for Greeter objects?
irb(main):039:0>Greeter.instance_methods=>[:say_hi,:say_bye,:instance_of?,:public_send,:instance_variable_get,:instance_variable_set,:instance_variable_defined?,:remove_instance_variable,:private_methods,:kind_of?,:instance_variables,:tap,:is_a?,:extend,:define_singleton_method,:to_enum,:enum_for,:<=>,:===,:=~,:!~,:eql?,:respond_to?,:freeze,:inspect,:display,:send,:object_id,:to_s,:method,:public_method,:singleton_method,:nil?,:hash,:class,:singleton_class,:clone,:dup,:itself,:taint,:tainted?,:untaint,:untrust,:trust,:untrusted?,:methods,:protected_methods,:frozen?,:public_methods,:singleton_methods,:!,:==,:!=,:__send__,:equal?,:instance_eval,:instance_exec,:__id__]Whoa. That’s a lot of methods. We only defined two methods. What’s goingon here? Well this isall of the methods for Greeter objects, acomplete list, including ones defined by ancestor classes. If we want tojust list methods defined for Greeter we can tell it to not includeancestors by passing it the parameterfalse, meaning we don’t wantmethods defined by ancestors.
irb(main):040:0>Greeter.instance_methods(false)=>[:say_hi,:say_bye]Ah, that’s more like it. So let’s see which methods our greeter objectresponds to:
irb(main):041:0>greeter.respond_to?("name")=>falseirb(main):042:0>greeter.respond_to?("say_hi")=>trueirb(main):043:0>greeter.respond_to?("to_s")=>trueSo, it knowssay_hi, andto_s (meaning convert something to astring, a method that’s defined by default for every object), but itdoesn’t knowname.
But what if you want to be able to view or change the name? Rubyprovides an easy way of providing access to an object’s variables.
irb(main):044:0>classGreeterirb(main):045:1>attr_accessor:nameirb(main):046:1>end=>[:name,:name=]In Ruby, you can reopen a class and modify it. The changes willbe present in any new objects you create and even available in existingobjects of that class. So, let’s create a new object and play with its@name property.
irb(main):047:0>greeter=Greeter.new("Andy")=> #<Greeter:0x3c9b0 @name="Andy">irb(main):048:0>greeter.respond_to?("name")=>trueirb(main):049:0>greeter.respond_to?("name=")=>trueirb(main):050:0>greeter.say_hiHi Andy!=>nilirb(main):051:0>greeter.name="Betty"=>"Betty"irb(main):052:0>greeter=> #<Greeter:0x3c9b0 @name="Betty">irb(main):053:0>greeter.name=>"Betty"irb(main):054:0>greeter.say_hiHi Betty!=>nilUsingattr_accessor defined two new methods for us,name to get thevalue, andname= to set it.
This greeter isn’t all that interesting though, it can only deal withone person at a time. What if we had some kind of MegaGreeter that couldeither greet the world, one person, or a whole list of people?
Let’s write this one in a file instead of directly in the interactiveRuby interpreter IRB.
To quit IRB, type “quit”, “exit” or just hit Control-D.
#!/usr/bin/env rubyclassMegaGreeterattr_accessor:names# Create the objectdefinitialize(names="World")@names=namesend# Say hi to everybodydefsay_hiif@names.nil?puts"..."elsif@names.respond_to?("each")# @names is a list of some kind, iterate!@names.eachdo|name|puts"Hello#{name}!"endelseputs"Hello#{@names}!"endend# Say bye to everybodydefsay_byeif@names.nil?puts"..."elsif@names.respond_to?("join")# Join the list elements with commasputs"Goodbye#{@names.join(", ")}. Come back soon!"elseputs"Goodbye#{@names}. Come back soon!"endendendif__FILE__==$0mg=MegaGreeter.newmg.say_himg.say_bye# Change name to be "Zeke"mg.names="Zeke"mg.say_himg.say_bye# Change the name to an array of namesmg.names=["Albert","Brenda","Charles","Dave","Engelbert"]mg.say_himg.say_bye# Change to nilmg.names=nilmg.say_himg.say_byeendSave this file as “ri20min.rb”, and run it as “ruby ri20min.rb”. Theoutput should be:
Hello World!Goodbye World. Come back soon!Hello Zeke!Goodbye Zeke. Come back soon!Hello Albert!Hello Brenda!Hello Charles!Hello Dave!Hello Engelbert!Goodbye Albert, Brenda, Charles, Dave, Engelbert. Comeback soon!......There are a lot of new things thrown into this final example that wecan take a deeper look at.