The problem is retraining class writers (myself included) to do
it the right way.
I don’t think retraining will solve the vast existence of codes
that have been written in the “old” way, including the basic Ruby
built-in classes themselves. That’s why I am very interested
whether from OO design point of view, the current design is
“flawed”. (I think OO has been around for a long time, so it is
hard to believe that this kind of problem is not
encountered/solved before.)
I think it is flawed. Personally.
This problem has little to do with static vs dynamic typing and
can easily occur in C++ programs.
Well, it may occur in C++ programs, but it is not the intention.
Suppose
derived a;
parent b;
parent c;
…
a = b + c;
Assuming that this code compiles and executes, here we are
guaranteed that the class of a is “derived” (i.e., a will respond
to methods that are defined for class derived). There may be some
semantic/logic error depending on the overloadings of the ‘+’ and
‘=’ operators, but that is a separate issue.
This is where Ruby’s typeless variables (not typeless objects)
causes problems. In the compiled language, the variable ‘a’ has a
distinct type. With respect to your example, I would expect that
‘a’ would take on the type of Parent in Ruby. What I don’t expect,
however, is for:
a = a + b
to take on the type of Parent. After all, we’re really doing:
a = a.+(b)
So the typeness of a should be carried, even though it’s the
Parent’s operator which is called. It’s rather like the operator had
been declared without ‘virtual’ in C++.
Matters are made rather worse because there’s no clear way of doing
typecasting (yes, there is ‘coerce’, but that’s not really
typecasting) of objects. Additionally, because the variables
themselves are typeless, doing:
a = b + a # a = b.+(a)
Will result in a being a reference to a Parent, even though in C++,
the result would remain a Derived because types are associated with
variables. Jim’s solution (self.class.new) works quite well for the
first case (a += b), but it works not at all for the second case (a
= b + a). It’s correct, and it’s consistent, but it still feels
wrong.
(There’s a point where, at least IMO, if you’re dealing with Parent
and Derived and only those two classes are involved, then the
results should be coerced into Derived. This, however, results in
problems if you have DerivedA and DerivedB, both children of Parent.
Which class should then be used as the result?)
It’s not an easy problem. Jim’s solution is a decent one, and it
might be that some syntactic sugar could be provided. If I do:
class Foo
def bar
Foo.new
end
end
it could be interpreted as:
class Foo
def bar
self.class.new
end
end
because we are in the context of “class Foo”. I’m not sure if this
would be a good idea or not, but it would at least make Jim’s
solution ‘automatic.’
-austin
– Austin Ziegler, austin@halostatue.ca on 2002.10.28 at 09.56.17
···
On Mon, 28 Oct 2002 23:49:39 +0900, William Djaja Tjokroaminata wrote:
Jim Weirich jweirich@one.net wrote: