[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tads3] 'inherited' and propNotDefined



BrenBarn@aol.com wrote:
> 
> Jesse Welton wrote:
> -----
> Perhaps something like this:
> 
>   class ShadowProxy: object
>     target = nil
>     propNotDefined(prop, [args])
>     {
>       return delegated target.(prop)(args...);
>     }
>   ;
> 
>   a: object
>     propNotDefined(prop, [args]) { "prop not defined: <<prop>>" }
>   ;
> 
>   p: ShadowProxy
>     target = a
>   ;
> 
> If we call p.xyz(), we get p.propNotDefined(&xyz), which delegates to
> a.xyz().  When we find that missing, lookup of propNotDefined must
> proceed from a, not p, for correct behavior.  For consistency,
> inherited lookups should proceed the same way, from the target.
> -----
> 
>        I see your point, but I don't think this example really parallels the 
> inheriting-undefined-properties situation, because there's no explicit 
> inheritance call.

No, but there is an explicit delegation call, which is a
generalization of inheritance.  It says: perform this method, using
self as the receiver, but beginning method lookup in this place.
Inheritance calls are precicely this, with "this place" being the
superclass (or superclass list).

>  This has got me thinking; let me give my perspective here.
> 
>        My thinking is that, for the purposes of resolving this
> issue, we should consider inherited() as nothing more than a
> convenient textual substitution for an explicit call to the
> corresponding method on the base class.  It relives us of the burden
> of having to manually sync the method name and class name (and it
> keeps the same self object and so forth) but essentially it is a
> call to a specific other method.

Not so.  This ignores the fact that the identity of self (the
receiver) must be preserved.

  A: object
    x = nil;
    setX(val) { x = val; }
  ;

  B: A
    setX(val)
    {
      "setting x to <<val>>";
      inherited(val);  // sets B.x, not A.x, so not equivalent to
                       // A.setX(val)
    }
  ;

>        To me, this clearly indicates that
> inheriting-into-a-propNotDefined lookup should NOT proceed from the
> target.  The inherited call should always be a call to the method of
> the base class, and should be looked up accordingly.  If no such
> method is found, propNotDefined should be called on the base class,
> because that's where we were looking for the inherited method.

You misunderstood what I meant by "target", then.  In the case of
inheritance, the target is the superclass.  It's not a well chosen
word, really.  What would be a better term for the place from which
lookup proceeds, applicable to both inheritance and delegation?

>        In addition, I think it might be fruitful to look for
> examples where we definitely would NOT want the inherited lookup to
> find a propNotDefined on the target object.  (I had an example but I
> think it was pretty hairbrained so I'll keep thinking.)  It seems
> that there could be situations where "inheriting" a propNotDefined
> on the target object would incorrectly delegate to the proxy object
> when what was intended was to inherit base class handling for the
> target object.

I can't think of a realistic example with 'inherited', but you could
take my example with 'delegated', remove the propNotDefined on a, and
assume the interface of a relies on the nil default for some reason.

-Jesse