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"!