In article 9lr1ou4okjrafjrq24pusqi8q9c9fbfkvt@4ax.com,
In Phil’s example, it seems like “meth” is testing the argument’s
class, not its type. According to my copy of Design Patterns, the
type of an object is the set of methods to which it can respond. If
two objects respond to the same set of methods then they have the same
type, even if they aren’t objects of the same class.
For me, testing an argument’s class is a code smell.
Yes, I tend to agree…
What do I care if
“s” is a Foo or a Bar, as long as it responds to the methods I need to
send it? I try to design my classes and methods so that, if I want
method “A” to accept as arguments objects that are created from
different classes, then each of the classes should implement the set
of methods that “A” will send. As far as “A” is concerned, all the
objects have the same type.
So, for the case where you want to “overload” concat to accept EITHER
String objects or Fixnum objects:
concat(“A”, “B”) → “AB”
concat(“A”, 1) → “A1”
concat(1, 2) → “12”
then you define concat as
def concat(arg1, arg2)
arg1.to_s + arg2.to_s
end
Since both String and Fixnum objects respond to to_s, they’re both the
same type as far as concat is concerned.
Yes, but what about an example like this (This is some actual code I have
which I hesitate to show because I’m sure it’s pretty smelly code, but
I’m also not sure how else to do this):
class Signal
#…
def assign_at (relTime=0,function=nil)
#schedule an event
nextValue = case function
when nil
Proc.new.call
when Proc
function.call
when Signal
proc{function.to_s}.call
else #should probably be Fixnum
function
end
@eventQueue[relTime] = nextValue
nextValInQueue = @eventQueue.shift
@next_value = nextValInQueue if nextValInQueue
end
def assign(function=nil)
if function
assign_at(0,function)
else
assign_at(0,Proc.new)
end
end
#…
end
The idea here is that I want Signal objects to be able to be assigned from
either Proc objects, other Signals, or values, like:
a = Signal.new(0)
b = Signal.new(1)
sig = Signal.new
sig.assign { a * b } #calculate a value based on values of a & b
sig.assign b #assign the value of b to sig
sig.assign 0 #assign 0 to sig
sig.assign_at(10,1) #assign 1 to sig @ time 10
How else could this be done? Proc objects, Signal objects and Fixnums
don’t really have much in common… But as was suggested earlier, perhaps
a method could be added to each of these classes in order to eliminate
testing the class of the argument. In this case it looks like a call
method could be added to Fixnum which would just return the value of the
number, but that wouldn’t be quite right since this branch of the case
would still need to be handled:
when Signal
proc{function.to_s}.call
...
Since a proc needs to be created from the signal in this case… I was
just getting around to looking at this piece of code to see if I could
clean it up and it seemed appropriate to show it in this context.
(Yeah, there’s some funky stuff going on here. This code snippet is from
RHDL, it lets Ruby look like a Hardware description language.)
Phil
···
Tim.Hunter@sas.com wrote: