Phil Tomson wrote:

> In article <3C153282.9000309 / vt.edu>, Roy Patrick Tan  <rtan / vt.edu> wrote:
> 
>>Phil Tomson wrote:
>>
>>
>>>then if I, or a user of these 
>>>classes decide that they want a different kind of runnable object that 
>>>performs a differnt function when 'run' is called, all they 
>>>have to do is define another class of their own and make sure it's objects 
>>>respond to 'run'.
>>>
>>
>>This is somehow disturbing to me. "Run" is kind of ambiguous, and might 
>>behave differently for different objects, whereas the caller of the 
>>method expects "run" to behave in a certain way, shouldn't a 
>>compiler/interpreter make sure that  it *does* behave that way (ie check 
>>the contract)?
>>
>>
> 
> But if the caller object "expects 'run' to behave in a certain way" 
> doesn't that imply that encapsulation is broken in the system?


in most cases, the caller does need to know the behavior of the method

it calls. For example, to be able to use it., the caller would 
reasonably have to know that "sqrt" returns the square root of a number.



> whole system much simpler.  (BTW: I do check the 'contract' for an object 
> prior to sending it out to a client - I make sure it responds_to 'run').


In this case, since you don't really care what "run" does perhaps 
dynamic typing works well. But it doesn't seem to me too hard to do the 
same in statically typed languages using multiple inheritance / interfaces.

for example (and this, unfortunately, is purely hypothetical), I have 
two kinds of objects, say a Car and a Calculator, both of which 
implement a method called "run". Then: a.) sometimes I want call the run 
method for Car objects, expecting it to run like a car, and similarly, 
b.) I want to call the run method of Calculator objects expecting them 
to run like calculators. But sometimes c.) I wish to call their run 
methods, not caring what kind of objects they are, so long as they 
implement the run method.

The answer seems to me to just declare an interface Runnable (in Java -- 
well some other name, since Runnable is already taken), or a purely 
abstract class in C++, so that if we wanted behavior a, we could:

Car c;
....
c.run();

For b:
Calculator c;
....
c.run();

For c:
Runnable r;
....
r.run();

Users who want to create their own runnable classes now need only to 
implement (or sublass) Runnable, with the added benefit(?) that static 
tpying brings.

 
> I know, it's difficult at first to move from the statically typed 
> worldview to a dynamically typed worldview - it's kind of like looking at 
> that popular optical illusion that looks at first like an old hag of a 
> woman with a big nose, but as you stare at it a bit longer you 
> see that within that image is a beautiful young woman.  It was like that 
> for me initially as well, at first I missed having type checking, but now 
> that I see it from the other side it is quite freeing and, dare I say it,  
> beautiful.


With what little programming in Ruby that I've done, I liked its dynamic 
typing for the convenience and flexibility, but I wonder, in the big 
scheme of things, if the benefits outweigh the disadvantages?

I forget who it was that said about high level languages, that it's 
chief advantage was that "if you cannot say it, you cannot say it wrong"!