what would YOU expect to happen here ?

Class Class1
   sub foo()
      msgbox currentmethodname
   end sub
end class

Class CustomClass1
  inherits Class1
   sub foo()
      msgbox currentmethodname
   end sub
end class

Window Window1
  Sub bar(c as Class1)
      msgbox currentmethodname
  end sub

  Sub bar(c as CustomClass1)
      msgbox currentmethodname
  end sub

  Function factory() as Class1
         return new CustomClass1
  End Function

  Event Open
        
        dim c as Class1

        c= factory()

        c.foo

        // have to do the check in this order because a CustomClass1 is also a Class1
       // but a Class1 instance is JUST a Class1 instance
        if c isa CustomClass1 then
           msgbox "c isa CustomClass1"
        elseif c isa Class1 then
           msgbox "c isa Class1"
        end if

        bar(c) // <<<<<<< this one might surprise you as to which one gets called !
  end event

End Window

Which BAR method do you expect will be called ?

The one for Class1 as the compiler picks it based on the variable type!

I was kind of hoping there’d be others who chimed in as thats VERY different from which Foo gets called :slight_smile:
Its downright surprising, not really intuitive, and IMHO a “weird” behaviour

Same as with properties which gets picked on variable type and not on actual class type. (as properties can’t be overwritten)

you dont find it weird that despite the local holding an instance of CustomClass1 that the wrong method is called ?

Well, I simply know that the compiler doesn’t include the isa check there.

You get the right behavior if bar is a method on the class.

[quote=479703:@Christian Schmitz]
You get the right behavior if bar is a method on the class.[/quote]
which is what I expect it should also do when its not

Fill a feature request?

already done
was just hoping others might respond with what they though should happen

Well, I don’t expect a C++ compiler to do this much better.

Window1.Bar(Class1) is called. This isn’t surprising to me. The hidden “self” parameter is the only parameter whose runtime type is taken into account in method overriding. For Window1.Bar() “self” is the Window object, all other parameters are typed according to their static type.

Xojo isnt C++ :stuck_out_tongue:

Trust me there is no hidden self and its not really relevant
Its handled differently and thats an internal implementation detail

The runtime type of the local IS well known
You can view it in the debugger and Isa will also do the right thing in the code that follows (see my code posted above)

Its ONLY the call of Bar that gets it wrong and that is because instead of determining which version to call at runtime its done at compile time
And THAT is the oddity (one that bites me from time to time as I am always surprised by this and then have to remind my self to do something different to work around this weirdness)

Here is C++ version which works in Xcode:

[code]#include

class Class1 {
public:
virtual void foo()
{
std::cout << FUNCTION << " in Class1
";
}
};

class CustomClass1 : public Class1 {
public:
virtual void foo()
{
std::cout << FUNCTION << " in CustomClass1
";
}
};

class Window {
public:
virtual void bar(Class1 *c)
{
std::cout << FUNCTION << " with Class1
";
}
virtual void bar(CustomClass1 c)
{
std::cout << FUNCTION << " with CustomClass1
";
}
virtual Class1
factory()
{
return new CustomClass1();
}

void test()
{
	Class1 *c = factory();
	c->foo();
	bar(c);
}

};

int main(int argc, const char * argv[]) {
// insert code here…
std::cout << "Hello, World!
";

Window w;
w.test();

return 0;

}[/code]

output is:

[quote]Hello, World!
foo in CustomClass1
bar with Class1
Program ended with exit code: 0[/quote]

So C++ also just calls function based on variable declaration.

of course IF xojo IS now consistent with C++ then when can we have postincrement (++) and postdecrement (–) ? :stuck_out_tongue:

principle of least surprise should be followed here regardless of what C++ does

That’s what I’m saying. The virtual method Window1.Bar is being dynamically dispatched based on the runtime type of Self/Window1, not the c parameter. But it’s not wrong, it’s single dispatch polymorphism.

Changing this behavior required matching method calls against signatures at runtime which would incur a performance penalty, no? This isn’t an issue when calling the method of a class.

I think it is fine and you as developer should use methods and overwrite them or do isa check yourself.

actually its decided at compile time and which to dispatch to is NOT determined at runtime in any way

which leads to fragile code as everytime you add a new subclass IF you have code that is stylistically like this then you have to make sure you add a new “select case” or “ISA” check for every new one you add

and THAT is why I see this as a problem

can it be designed around ?
many times yes
but not always

and therein lies the problem
for instance

Module Module1 
  Class Class1
     sub foo()
        msgbox currentmethodname
     end sub
  end class

  Class CustomClass1
    inherits Class1
     sub foo()
        msgbox currentmethodname
     end sub
  end class

  Sub bar(extends c as class1)
                msgbox currentmethodname
   End sub

  Sub bar(extends c as CustomClass1)
                msgbox currentmethodname
   End sub

End Module

Window Window1
  Event Open
        
        dim c as Class1

        c= new CustomSubclass

        c.foo

        // have to do the check in this order because a CustomClass1 is also a Class1
       // but a Class1 instance is JUST a Class1 instance
        if c isa CustomClass1 then
           msgbox "c isa CustomClass1"
        elseif c isa Class1 then
           msgbox "c isa Class1"
        end if

        c.bar // <<<<<<< this one might surprise you as to which one gets called !
  end event

End Window

again we have much the same issue
and IF you extend a built in class you dont have always have the same options to deal with this like you might if it was your own code

if it has that big a penlty then we probably need to worry about how virtual methods in classes are handled as thats a similar dynamic dispatch mechanism