From: Austin Ziegler Date: 2006-08-08T08:58:02+09:00 Subject: Re: How to react on nil or wrong object-type as parameter On 8/7/06, Yochen Gutmann wrote: > So if I do understand you all correctly, in Ruby you put the > responsible to the caller of a method (eg print_salary()). If you want > to test that method, you test it only with the proper types. Where type may not be related to the Object's class or inheritance tree. An object's type for any method call is explicitly related to whether it responds to the method we're looking for with the arguments we provide and the sort of return value we're wanting. It's significantly different than Java in this way. > The next thing would be testing the method which includes the call of > print_salary() if it calls this methods with the wrong types of > parameter. Is this right? Um, not really as I understand it. > One problem in this concept is that if some operations might work on a > parameter-object and the following is not the exception is thrown when > the object is already modified. There are problems with your example code: > class Bank > @invitations_to_golf This won't do what you expect. Try: > def handle_client_well client > client.decrease_acoount(200) > client.check_portfolio > @invitations_to_golf.push client > end > > end class Bank def initialize @invitations_to_golf = [] end def issue_golf_invitations(title, sender, message, date) @invitations_to_golf.each { |client| client.send_message title, sender, message, date } end def treat_client_well(client) if client.check_portfolio client.decrease_account(200) @invitations_to_golf << client end end end What this does is that it requires that all clients have a #check_portfolio method. If the Bank's clients aren't guaranteed to have that, you'll blow up here, as you've suggested. But how do you deal with that? Well, you don't look for a VeryRichClient. You do one of two things: class Client def check_portfolio nil end end class LowBudgetClient < Client end class VeryRichClient < Client def check_portfolio true end end So you modify the object you're dealing with and expect to pass in so that it always has a check_porfolio (that's why I put the "if" test, which you'd want anyway) or you do: class Bank def treat_client_well(client) if client.respond_to?(:check_portfolio) and client.check_portfolio client.decrease_account(200) @invitations_to_golf << client end end end Or you handle your call a bit better: jon_doe = LowBudgetClient.new big_boss = VeryRichClient.new big_money = Bank.new big_money.handle_client_well big_boss big_money.handle_client_well jon_doe rescue nil One need not be explicit about how you handle a lot of things in Ruby. Strictly speaking, you'd *never* want to have two classes for clients in this way, but you may have things in the contents of the clients which allow you to do things smarter. -austin -- Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/ * austin@halostatue.ca * http://www.halostatue.ca/feed/ * austin@zieglers.ca