Quantcast

Re: [groovy-jsr] when is super.foo(o)=="bar"?

Previous Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [groovy-jsr] when is super.foo(o)=="bar"?

tugwilson

On 28 Oct 2005, at 23:10, Jochen Theodorou wrote:

> Dierk Koenig wrote:
>
>>>> well, I don't think it was an optimisation. I think it was more  
>>>> the  only way to implement that without changing the invoke  
>>>> signatures  in MetaClass completly.
>>>>
>>>
>>> Really? Wouldn't getting the MetaClass for the superclass and  
>>> calling  inkokeMethod on that work OK (this is a genuine  
>>> question; I *think*  it would be OK but I'm not certain)
>>>
>
> to clarify things, we know the superclass during compile time. We  
> have to know it for different reasons. Calling the method of the  
> super class is in general not possible since the dispatching  
> depends on runtime types (if we do groovy dispatching). If the  
> superclass overwrites or defines getMetaClass, then this method  
> should be used I think. But I have to take a look into the  
> implementation first, because if MetaClass uses this.getClass() or  
> something like that to produce the MetaClass it should give the  
> wrong MetaClass or not? And I am sure a class subclassing a groovy  
> class in groovy does overwrite getMetaClass nor does it a javaclass  
> subclassing a groovy class that is called from groovy. But when I  
> think about it... that would mean overwriting getMetaClass to  
> return a different MetaClass than usual would then change the  
> behavior of the superclass too... oh that sounds bad for me.
>
> But in case of super.foo(o), why should the dispatching be done  
> with the MetaClass of the superclass? I think the new MetaClass  
> should do that. If that class defines different dispatching rules  
> then why not for the super.foo(o) call too?
>
> > I would agree that calling the superclass impl of the method
> > via obj.super().invoke() would be preferrable while I
> > have no idea about the technical feasiblity.
> > Points to consider:
> > - super overrides invokeMethod()
> > - super overrides getMetaClass()
> > - object and super may both be or not GroovyObject
> >   (all 4 combinations possible)
>
> it's work of the MetaClass to call invokeMethod and to decide when  
> it is time to do that (I well know that currently this is done by  
> Invoker, but I think that's very wrong). So it's more a question of  
> what the correct MetaClass is and how to get it. For jsr, what is  
> the correct MetaClass, if any?


I have thought some more about this:

I think that calling via the superclass's MetaClass will produce the  
correct behaviour - having invokeSuperMethod(), get/setSuperProperty  
and get/setSuperAttribute looks OK to me. The default implementation  
would just delegate the calls to the superclass' MetaClass so the  
implementation is pretty trivial.

However there are other interesting problems:

If b is of type B which subclasses A; what should happen with (b as  
A).foo(1, 2, 3)?

It is wrong to call foo via the MetaClass for B -  if A has foo(long,  
long, long) and B has foo(int, int, int) then b.foo(1, 2, 3) should  
call the foo on B and (b as A).foo(1,2,3)  should call the foo on A.  
Calling via B's MetaClass will not give that behaviour.

It is also wrong to call via the metaClass for A -  if A has foo(int,  
int, int) and B has foo(int, int, int) then b.foo(1, 2, 3)  and (b as  
A).foo(1,2,3)  should both call the foo on B. Calling via A's  
MetaClass will not give that behaviour.

This leads me to believe that the MetaClass needs a getMetaClass
(Class) method which returns a MetaClass with suitable behaviour for  
this case.

You have raised an interesting set of issues here;)

BTW executing (b as A).foo() using CVS HEAD produces a very starnge  
result. foo is called on b Ok but then there appears to be an attempt  
to call a static foo on A!

John Wilson
The Wilson Partnership
http://www.wilson.co.uk


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [groovy-jsr] when is super.foo(o)=="bar"?

Jochen Theodorou
John Wilson wrote:
[...]
> I have thought some more about this:
>
> I think that calling via the superclass's MetaClass will produce the  
> correct behaviour - having invokeSuperMethod(), get/setSuperProperty  
> and get/setSuperAttribute looks OK to me. The default implementation  
> would just delegate the calls to the superclass' MetaClass so the  
> implementation is pretty trivial.

if it is no problem to get this superclass, then ok.

> However there are other interesting problems:
>
> If b is of type B which subclasses A; what should happen with (b as  
> A).foo(1, 2, 3)?

I think of "as" as a transformation, rather than the cast operation
which does only change the compiletime type. But please note, the above
used with a code does in java only make a difference when foo is static
or the foo in B does not overwrite the foo in A (foo could be private in
A for example). Java would always call the modified version of foo from
b if it is overwritten. If "as" does make an A out of an B, and does
this by more than a cast, then does it make a difference. But then you
can't call foo on B since the object is no longer a B.

> It is wrong to call foo via the MetaClass for B -  if A has foo(long,  
> long, long) and B has foo(int, int, int) then b.foo(1, 2, 3) should  
> call the foo on B and (b as A).foo(1,2,3)  should call the foo on A.  
> Calling via B's MetaClass will not give that behaviour.

that's a case where foo is not overwritten, so it should be the foo from
A, yes, but using the MetaClass from B would result in the same I
thought. Why wouldn't it? The MetaClass from B has also all methods from A.

> It is also wrong to call via the metaClass for A -  if A has foo(int,  
> int, int) and B has foo(int, int, int) then b.foo(1, 2, 3)  and (b as  
> A).foo(1,2,3)  should both call the foo on B. Calling via A's  MetaClass
> will not give that behaviour.
>
> This leads me to believe that the MetaClass needs a getMetaClass (Class)
> method which returns a MetaClass with suitable behaviour for  this case.

hmmm... it would be enough to use that class as extrapoint in the method
selection. We could first select the methods by name as we do now, then
remove all methods which are not suitable for the given class.

> You have raised an interesting set of issues here;)

hehe, yes. That just shows how unspecified groovy is.

> BTW executing (b as A).foo() using CVS HEAD produces a very starnge  
> result. foo is called on b Ok but then there appears to be an attempt  
> to call a static foo on A!

oh! These parts are really broken *sigh*

bye blackdrag
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [groovy-jsr] when is super.foo(o)=="bar"?

tugwilson

On 29 Oct 2005, at 16:05, Jochen Theodorou wrote:

>
> if it is no problem to get this superclass, then ok.

getting the MetaClass for the superclass is no problem.

>
>
>> However there are other interesting problems:
>> If b is of type B which subclasses A; what should happen with (b  
>> as  A).foo(1, 2, 3)?
>>
>
> I think of "as" as a transformation, rather than the cast operation  
> which does only change the compiletime type. But please note, the  
> above used with a code does in java only make a difference when foo  
> is static or the foo in B does not overwrite the foo in A (foo  
> could be private in A for example). Java would always call the  
> modified version of foo from b if it is overwritten. If "as" does  
> make an A out of an B, and does this by more than a cast, then does  
> it make a difference. But then you can't call foo on B since the  
> object is no longer a B.
>
>
>> It is wrong to call foo via the MetaClass for B -  if A has foo
>> (long,  long, long) and B has foo(int, int, int) then b.foo(1, 2,  
>> 3) should  call the foo on B and (b as A).foo(1,2,3)  should call  
>> the foo on A.  Calling via B's MetaClass will not give that  
>> behaviour.
>>
>
> that's a case where foo is not overwritten, so it should be the foo  
> from A, yes, but using the MetaClass from B would result in the  
> same I thought. Why wouldn't it? The MetaClass from B has also all  
> methods from A.
>
>
>> It is also wrong to call via the metaClass for A -  if A has foo
>> (int,  int, int) and B has foo(int, int, int) then b.foo(1, 2, 3)  
>> and (b as  A).foo(1,2,3)  should both call the foo on B. Calling  
>> via A's  MetaClass will not give that behaviour.
>> This leads me to believe that the MetaClass needs a getMetaClass  
>> (Class) method which returns a MetaClass with suitable behaviour  
>> for  this case.
>>
>
> hmmm... it would be enough to use that class as extrapoint in the  
> method selection. We could first select the methods by name as we  
> do now, then remove all methods which are not suitable for the  
> given class.

I'm not sure I have explained this correctly. Let me try an example:

class A {
     foo(int p) {println "foo(p) in A"}
     foo(long p, long q) { println "foo(p, q) in A"}
}

class B extends A  {
     foo(int p) {println "foo(p) in B"}
     foo(int p, int q) { println foo(p, q) in B"}
}


B b = new B()
A a = b

a.foo(1)         // should print "foo(p) in B"
a.foo(1, 2)     // should print "foo(p, q) in A"

b.foo(1)         // should print "foo(p) in B"
b.foo(1, 2)     // should print "foo(p, q) in B"

as B overrides foo(int) then this method is always called no matter  
what the type of the variable holding the object is.

B does not override foo(long, long) so when foo(1, 2) is called on  
via a variable of type A then the method defined in A is used. When  
it is called via a variable of type B then foo(int, int) is called  
because there is a closer match to the type of the actual parameters.

(This is the expected behaviour if we are following the Java rules.  
We already know that we can't always follow the Java rules for other  
things (like accessing private fields) so it may be acceptable for us  
to do this differently)


If we do want to deliver the behaviour above then we can't do it  
using our existing MetaClass implementation (at least, I can't see  
how to do it).

Do you agree that the above behaviour is the "correct" behaviour and,  
if so, do you think it matters if we deviate from this behaviour. I  
think that at the moment (if there were not some strange bugs) we  
would get the following behaviour:


a.foo(1)         // would print "foo(p) in B"
a.foo(1, 2)     // would print "foo(p, q) in A"

b.foo(1)         // would print "foo(p) in B"
b.foo(1, 2)     // would print "foo(p, q) in A"


John Wilson
The Wilson Partnership
http://www.wilson.co.uk


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [groovy-jsr] when is super.foo(o)=="bar"?

Jochen Theodorou
John Wilson schrieb:
[...]

> I'm not sure I have explained this correctly. Let me try an example:
>
> class A {
>     foo(int p) {println "foo(p) in A"}
>     foo(long p, long q) { println "foo(p, q) in A"}
> }
>
> class B extends A  {
>     foo(int p) {println "foo(p) in B"}
>     foo(int p, int q) { println foo(p, q) in B"}
> }
>
>
> B b = new B()
> A a = b
>
> a.foo(1)         // should print "foo(p) in B"
> a.foo(1, 2)     // should print "foo(p, q) in A"
>
> b.foo(1)         // should print "foo(p) in B"
> b.foo(1, 2)     // should print "foo(p, q) in B"


if we where in Java this would be correct, yes, but Java has no runtime
typing like groovy has.
atm we have

a.foo(1,2)== b.foo(1,2)

[...}
> If we do want to deliver the behaviour above then we can't do it  using
> our existing MetaClass implementation (at least, I can't see  how to do
> it).

a method would need the additional information if it is overwriting a
former implementation. For exmaple with using a pointer to the former
implementation. Then this has to be used instead.

> Do you agree that the above behaviour is the "correct" behaviour and,  
> if so, do you think it matters if we deviate from this behaviour.

If the above is correct, then any deviation would not be correct. And I
think it may matter if don't give people the ability to somehow choose
the method that should be called. This is not Self.
Loading...