what would YOU expect to happen here ?

That doesn’t agree with my observations:

  Dim obj As Class1
  If runtimecondition=True Then
      obj = New Class1
  Else
     obj = New CustomClass1
  End If
  obj.Foo() // decided at runtime based on the (sub)type used to instantiate obj

thats not the problem I was outlining
Dynamic dispatch to instance methods works as I expect

I’ve trimmed the code down to illustrate the issue I’m referring to

Class Class1
end class

Class CustomClass1
  inherits Class1
end class

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

  Sub bar(c as CustomClass1)
      msgbox currentmethodname
  end sub

  Event Open
        
        dim c as Class1

        c= new CustomClass1

        // 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

the code is all legal and compiles cleanly (or should) but the BAR that gets called is NOT what you might anticipate

They are both virtual methods of Window1, meaning dynamic dispatch looks at the runtime type Window1, not the runtime type of other parameters. Bar(CustomClient) can only be called with a parameter whose compile time type is CustomClient.

its not dispatched by any kind of runtime dynamic dispatch

but … I give up …

Not really, but you do introduce the overhead of introspection. If you put this at the top of bar(c As Class1) things will work as you expect with no future manual intervention, add more SubClasses and they will be called if passed.

Dim ti As Introspection.TypeInfo = Introspection.GetType(c) If ti.BaseType <> Nil Then Dim CurrentMethodNameShort As String = right(CurrentMethodName, len(CurrentMethodName) - len(Introspection.GetType(Me).Name) - 1) For Each m As Introspection.MethodInfo In Introspection.GetType(Me).GetMethods If m.Name = CurrentMethodNameShort Then For Each p As Introspection.ParameterInfo In m.GetParameters If p.ParameterType.Name = ti.Name Then Dim v() As Variant v.Append(c) m.Invoke(Me, v()) Return End If Next End If Next End If

Edit: YMMV for extends, I’ve not played with that in this demo

ick :slight_smile:
I’ll use my other work arounds for this and the extends issue which is nearly the same issue

:slight_smile:

wasnt really looking for work arounds - much as I appreciate the creativity of that option
more just a “does this make any damned sense to you that it behaves this way ?”

yes I get that C++ might behave this way
Xojo isnt C++ so why the heck would we expect it would behave the same ?
Would seem to me that making this do what a lot of people might expect it to do would be a good thing
At least at first glance it makes sense it would dispatch through a dynamically looked up means much like an instance virtual dispatch is done

BUt … oh well …

AS Xojo users we are conditioned to only think in workarounds! :wink:

-Karen

[quote=479752:@Karen Atkocius]AS Xojo users we are conditioned to only think in workarounds! :wink:
[/quote]
does this behaviour make any sense to you ?
I stumble on it every once in a whilte, smack my head and go “Oh yeah it does this thing in a way that makes no sense” write something different and move on
I finally filed a bug report & feature request about it

[quote=479753:@Norman Palardy]does this behaviour make any sense to you ?
I stumble on it every once in a whilte, smack my head and go “Oh yeah it does this thing in a way that makes no sense” write something different and move on
I finally filed a bug report & feature request about it[/quote]
It does make sense though. Methods on the class are virtual. Methods outside the class (ie. on the window) are not. Changing it would make Xojo completely different from other OO languages.

Was going to say that I would expect the Class1 version to be called (ie: what Xojo actually does), and that this is what would be expected as “dim c as Class1” has implied that “c” is to be treated as Class1 and not CustomClass1.

But then on the other hand, as a work around, adding “foo” to classes:

Public Sub foo(w as Window1) msgbox currentmethodname + " with Class1" End Sub

and

Public Sub foo(w as Window1) msgbox currentmethodname + " with CustomClass1" End Sub

…and then calling from “Open”:

c.foo( self )

to “get around” the problem, so to speak, ie: different code depending on actual class, does call the “right” method.

So if I was being strict that “dim c as Class1” is implying that c be treated as Class1, it’s the Class1 “foo” that should be called, but of course, it’s not.

So I have to admit, I can see OP’s point … it is a bit inconsistent, in a sense. Of course, that other OO languages would treat it all in exactly the same way, just makes them inconsistent as well.

This is one which drives me bonkers (sometimes, when I make the mistake of thinking about it):

Take a class, Class1, with private property “counter”:

Private Property counter as Integer = 0

… and public method “test”:

[code]Public Sub test()

me.counter = me.counter + 1

var instance2 as Class1 = new Class1()

instance2.counter = 200

End Sub[/code]

Somewhere else, try:

[code]var instance1 as Class1 = new Class1()

instance1.test()

instance1.counter = 100 // problem, won’t run as “counter” is private[/code]

All OK, apart from the last line, where I’m told “counter” is private.

In my naivety, I had always expected that “counter” would also be private where I access it on “instance2” in the test method.

ie: that yes, you can access the property from the “me” object, but not for other instances.

And having tried similar on C++ and C# and PHP environments, they all do the same, so clearly it’s my misunderstanding and is the way they are supposed to work, and not a mistake.

Turns out I’ve been wrong for decades …

Let me just say this
I asked a person who is very familiar with compilers & compiler engineering and Xojo my question
The reply was

It might make things slightly slower, and it could possibly break existing code
And may have an impact on plugins - these thigns are unclear to both of us

But it might make this behaviour less “surprising” in how it behaves

Yes, the compiler could detect there are several variants and then check with isa the parameter and call the most specific one matching the class.

Same with variants where you could have a method taking variant/auto and a more specific ones with integer or string and the compiler could check what’s inside the variant/auto object.

or this case could just use dynamic dispatch like it already does for the virtual methods of class instances :stuck_out_tongue:

My gut reaction is that there is a deeper problem with the application’s object model if Window1 needs to know about specific children of Class1. That problem might feel less painful if Xojo dispatched your Window1 methods based on the actual input parameter type rather than the declared type of the variable feeding said parameter. But it would still be a problem.

Window1 should not need to know anything about the children of Class1. Ideally, Window1 should not even know about Class1. It should instead know about Interface1 which Class1 implements, and which all of Class1’s children implement through inheritance. But whether you choose to utilize an explicit interface or not, Window1 should be absolutely blind to the fact that Class1 has children.

Subclass specific behavior should be hidden in the subclass and abstracted behind common methods, defined in Class1, which Window1 can call. So there should be a single Window1.Bar method which takes Class1 as input and calls Class1.Foo. Which of course will dispatch based on the actual underlying type.

Now I’ll be the first to admit that you can run into situations in the real world where OOP design principles (or any design principles) have to bend or even break because of the constraints of the moment. Heck, I actually used GOTO once because in that one rare instance it radically cleaned up a function that was handed to me and made the logic easy to follow (believe it or not). But if I found myself in a situation where Window1 needed to know about all of Class1’s children…and it wasn’t a quick/dirty one off app that I just needed for the moment…I would stop and rethink the object model.

I completely understand what you’re saying
It misses the point. I wasnt asking about design advice etc.

The problem I outlined above also manifests itself in much the same fashion if you use extension methods.
You get the exact same issue where the declared types extension is called and NOT any subclass extension IF there is one.

Basically the ONLY methods that are dynamically dispatched are instance methods and everything ese relies on the declared type.

Whether that is consistent with other OOP languages is really immaterial.
To the uninitiated it will be damned surprising and I’m sure there are a whole category of “bugs” like this in peoples code over the years because what you expected to happen didnt - and so instead we all write select case or if then else and casts to make things behave the way they should because “that thing contains a reference to this subclass but the superclass method is being called”

That design decision FORCES your code in some places to HAVE to know about subclasses and child types - which you rightly say is a bad thing and maybe could/should be hidden behind an interface or inherited API so it an be dynamically disptached.

That said the powers that be have said they dont see this is a bug … so this horse can remain unbeaten

FWIW I have dealt with this in a different fashion and moved on