Hi --

On Mon, 28 May 2007, Erwin Abbott wrote:

> On 5/27/07, dblack / wobblini.net <dblack / wobblini.net> wrote:
>>> I think it works pretty well, but I'd like to know what you prefer
>>> instead. I realize distinguishing objects by class is not encouraged,
>>> but I find myself needing it often, for better or worse.
>> 
>> But you're running aground on exactly why it isn't encouraged: namely,
>> it doesn't give you definitive information about the object's behavior
>> or interface.
>
> Say you have some method that accepts various objects that represent a
> time. It's job is to return true if the given time is more than a week
> old. We have DateTime, Time, Date, and probably some more I don't know
> about. We can test that these objects have a comparison operator, and
> not pay attention to their class, but that doesn't help me because
> Date.new < Time.now doesn't work. In fact, Date's <=> checks if it was
> passed an Integer or a Date object, because knowing the object's class
> is necesarry to know how to compare them.
>
> I don't see any other way to write that method, am I missing
> something? It seems the most definitive information about any objects
> behavior is its source code, next to that we can ask what class it is
> and look up the documentation. I agree distinguishing objects by class
> has its problems, like Date#<=> doesn't work with anything but Dates
> and Integers (when maybe it should be testing respond_to? :ajd when it
> isn't given an Integer), but is there a better alternative?
>
>> Are you sure a mixin wouldn't make more sense?
>
> Instead of using a proxy? It's a trade-off at this point between
> getting case to work and having to write code that can't use intstance
> variable names like @id or @name because the original object might
> already be using them, or having to alias an existing #name as
> #old_name and making sure my #name doesn't break any code in that
> class. I might still break something with a proxy class answering
> #name, but it won't break the underlying object when it calls name on
> itself. I think at this point I'll accept that case statements won't
> work, but I'm going to try a few other things before giving up.

I was thinking of something like (semi-tested only):

   module DateComp
     def <(other)
       Time.parse(strftime("%m/%d/%y")) < other
     end
   end

   d = Date.new.extend(DateComp)
   your_method(d)

That way, you can use duck typing in the method itself, which means
that you don't have to change the method if you want to provide it
with other objects; you just have to prepare things on the calling
end.  You might have to have a more complex mixin for your proxy case,
but anyway, that's the kind of thing I was thinking about.


David

-- 
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying!  http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)