[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: a class that looks like (kind_of?) several classes

Eric Mahurin

5/10/2005 6:21:00 PM

> > > > Is there a way to make a class that looks like several
> > > classes?
> > > > For example:
> > > >
> > > > class IOArray < IO
> > > > include Array # doesn't work because Array is not a
> > > Module
> > > > # use IO methods calls to accomplish the Array
> methods
> > > > end
> > > >
> > > > I don't need multiple inheritance. All I want is these
> > > > additional classes to appear in the ancestors list. In
> the
> > > > above example, IOArray could act like an IO or an
> Array.
> > > It
> > > > looks like evil.rb might have a solution, but is there
> a
> > > > non-evil way?
> > >
> > > class IOArray < IO
> > > def kind_of?(cl)
> > > Array == cl || super
> > > end
> > > end
> >
> > Yep, that is pretty obvious. I think that is all I need,
> but I
> > guess overriding ancestors would complete this.
> >
> > > >> x=IOArray.allocate
> > > => #<IOArray:0x10184258>
> > > >> x.kind_of? Array
> > > => true
> > >
> > > But seriously, for what do you need that? I can't think
> of
> > > an application
> > > where I would want to make something look like an Array
> > > without being one.
> > > Maybe it's rather Enumerable that you want?
> >
> > Enumerable doesn't have random access and can't modify like
> > Array (or String). I think it would have been nice to have
> a
> > module like "Indexable" that would cover common methods in
> > Array and String.
> >
> > The example I have above should probably be combining an IO
> and
> > a String since an IO accesses characters like a String:
> >
> > class IOString < IO
> > def kind_of?(c); String==c || super; end
> > # use IO methods (seek/tell/read/write) to accomplish
> > # the String methods
> > end
>
> This is generally unneeded in Ruby; If duck typing is used
> properly,
> the ancestors and kind_of? shouldn't matter. And if it *does*
> matter,
> then masquerading like this could cause problems:
>
> if obj.kind_of? String
> var.replace obj
> end
>
> This code would break if obj is an IOString as defined above,
> even
> though this code has no logic errors.
>
> If you check out the StringIO class (require 'stringio'), you
> will
> find that it inherits neither from IO nor String. But it
> still works
> very nicely :)


Thanks. I assumed that the StringIO class inherited from the
IO class since it has all of the same methods. So the proper
Ruby style is to use respond_to? instead of kind_of? to see
what "type" your arguments are?

You still should be able to make the above "replace" code work
above. For the IOString class I described, you'd just replace
the contents of the file with the string passed. seek(0);
truncate(write(value)). That would seem to accomplish the
replace function.





__________________________________
Do you Yahoo!?
Yahoo! Mail - You care about security. So do we.
http://promotions.yahoo.co...


2 Answers

Mark Hubbart

5/10/2005 6:55:00 PM

0

On 5/10/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:
> > > > > Is there a way to make a class that looks like several
> > > > classes?
> > > > > For example:
> > > > >
> > > > > class IOArray < IO
> > > > > include Array # doesn't work because Array is not a
> > > > Module
> > > > > # use IO methods calls to accomplish the Array
> > methods
> > > > > end
> > > > >
> > > > > I don't need multiple inheritance. All I want is these
> > > > > additional classes to appear in the ancestors list. In
> > the
> > > > > above example, IOArray could act like an IO or an
> > Array.
> > > > It
> > > > > looks like evil.rb might have a solution, but is there
> > a
> > > > > non-evil way?
> > > >
> > > > class IOArray < IO
> > > > def kind_of?(cl)
> > > > Array == cl || super
> > > > end
> > > > end
> > >
> > > Yep, that is pretty obvious. I think that is all I need,
> > but I
> > > guess overriding ancestors would complete this.
> > >
> > > > >> x=IOArray.allocate
> > > > => #<IOArray:0x10184258>
> > > > >> x.kind_of? Array
> > > > => true
> > > >
> > > > But seriously, for what do you need that? I can't think
> > of
> > > > an application
> > > > where I would want to make something look like an Array
> > > > without being one.
> > > > Maybe it's rather Enumerable that you want?
> > >
> > > Enumerable doesn't have random access and can't modify like
> > > Array (or String). I think it would have been nice to have
> > a
> > > module like "Indexable" that would cover common methods in
> > > Array and String.
> > >
> > > The example I have above should probably be combining an IO
> > and
> > > a String since an IO accesses characters like a String:
> > >
> > > class IOString < IO
> > > def kind_of?(c); String==c || super; end
> > > # use IO methods (seek/tell/read/write) to accomplish
> > > # the String methods
> > > end
> >
> > This is generally unneeded in Ruby; If duck typing is used
> > properly,
> > the ancestors and kind_of? shouldn't matter. And if it *does*
> > matter,
> > then masquerading like this could cause problems:
> >
> > if obj.kind_of? String
> > var.replace obj
> > end
> >
> > This code would break if obj is an IOString as defined above,
> > even
> > though this code has no logic errors.
> >
> > If you check out the StringIO class (require 'stringio'), you
> > will
> > find that it inherits neither from IO nor String. But it
> > still works
> > very nicely :)
>
> Thanks. I assumed that the StringIO class inherited from the
> IO class since it has all of the same methods. So the proper
> Ruby style is to use respond_to? instead of kind_of? to see
> what "type" your arguments are?

The usual Ruby way is to use Duck Typing. As I see it:
- If you are accepting different kinds of objects in the same method,
use respond_to? to determine how to use them.
- If you only expect one kind of argument, don't even bother checking.

So:

# takes a file or a filename
def read_data(file)
if file.respond_to? :read
file.read
else
File.open(file){|f| f.read}
end
end

# takes an string
def show_in_quotes(str)
puts '"' + str + '"'
end

> You still should be able to make the above "replace" code work
> above. For the IOString class I described, you'd just replace
> the contents of the file with the string passed. seek(0);
> truncate(write(value)). That would seem to accomplish the
> replace function.

Add that to a to_str method, and you'll have it. My example was
flawed; the Ruby interpreter won't decide that it's a String anyway.
But I still think that it could cause problems...
cheers,
Mark


Jim Weirich

5/10/2005 7:40:00 PM

0


Eric Mahurin said:

> Thanks. I assumed that the StringIO class inherited from the
> IO class since it has all of the same methods. So the proper
> Ruby style is to use respond_to? instead of kind_of? to see
> what "type" your arguments are?

The common Ruby style is to not check at all, but just send the messages
needed to get the job done. If the object is inappropriate, Ruby will
catch it and let you know what it didn't like.

--
-- Jim Weirich jim@weirichhouse.org http://onest...
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)