what would YOU expect to happen here ?

  1. ‹ Older
  2. 2 weeks ago

    Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    @Michael Hszlig;mann 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.

    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

  3. Andrew L

    Mar 19 San Francisco, CA, USA

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

    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

  4. Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air
    Edited 2 weeks ago

    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

  5. Andrew L

    Mar 19 San Francisco, CA, USA

    @Norman P 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.

  6. Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    its not dispatched by any kind of runtime dynamic dispatch

    but ... I give up ...

  7. Julian S

    Mar 19 Pre-Release Testers, Xojo Pro UK
    Edited 2 weeks ago

    @Norman P 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

    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

  8. Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

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

  9. Julian S

    Mar 19 Pre-Release Testers, Xojo Pro UK

    :)

  10. Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air
    Edited 2 weeks ago

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

  11. Karen A

    Mar 19 Pre-Release Testers

    AS Xojo users we are conditioned to only think in workarounds! ;)

    -Karen

  12. Norman P

    Mar 19 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    @Karen A AS Xojo users we are conditioned to only think in workarounds! ;)

    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

  13. Jason K

    Mar 20 Pre-Release Testers

    @Norman P 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

    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.

  14. Edited 2 weeks ago

    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.

  15. 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":

    Public Sub test()
    
      me.counter = me.counter + 1
      
      var instance2 as Class1 = new Class1()
      
      instance2.counter = 200
      
    End Sub

    Somewhere else, try:

    var instance1 as Class1 = new Class1()
    
    instance1.test()
    
    instance1.counter = 100    // problem, won't run as "counter" is private

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

  16. Norman P

    Mar 20 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

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

    Yes, but it would be a pretty drastic behavioral change. Doing this at runtime is called "dynamic dispatch" and some languages have the notion; there's no reason Xojo couldn't from a technical perspective (that I'm aware of, anyway).

    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

  17. Christian S

    Mar 20 Pre-Release Testers, Xojo Pro, XDC Speakers, Third Party Store Germany

    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.

  18. Norman P

    Mar 20 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

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

  19. Daniel T

    Mar 22 Pre-Release Testers, Xojo Pro

    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.

  20. Norman P

    Mar 22 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    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

or Sign Up to reply!