Method signatures

I know I’ve probably used this term a bunch in other blog posts but I don’t think I’ve ever explained what a method signature is.

In Xojo a “method signature” is the unique way Xojo identifies each method so it can know which method you are calling in your code.

So what does that include ?

First off it does NOT include the SCOPE. PRIVATE, PUBLIC, GLOBAL, and PROTECTED are scope modifiers – but they are not part of the signature of a method.

Attributes are also not part of the signature.

And, curiously enough, the return type is NOT part of the signature. While that determines where you can use the method (ie in an expression where a value is expected vs not) it is NOT part of the signature.

The signature includes only the name and parameter list.

It gets a LOT more confusing if your parameter lists have optional or default parameter values since the signature basically can be thought to be “variable” – but its still just the name and parameter list.

And if you ever get an error saying

There is more than one item with this name and it’s not clear to which this refers.

and the compiler has hilighted a method call then the likelihood is you have two signatures that can be treated the same and the compiler cannot figure out which one you really meant to use.

2019r3

I’ll admit that I really haven’t seriously touched R3 since most of its focus was on iOS and dark mode which isn’t something that matters to me.

The times I did start it I found it to still be slow like R2.1 and otherwise not many significant differences in the things I was trying.

Autocomplete is still glaringly bright in dark mode on macOS. I’m now wishing there was a way to turn autocomplete off its so hard on my eyes being in bold and bright white. It’s definitely NOT the code editors text color or any user selected color.

And the new default color set is harsh as well. Again its incredibly bright and in dark mode its too darned bright for my liking. Makes me really glad I made it so users could configure their own themes way back when 😛

But you be the judge. In the following pictures R3 is first and R1 is next. Both are set to use default colors. (To be honest the images do NOT show how bright those colors are here on all 3 monitors)

R3 in default colors in dark mode are very bright
R1 default colors are subdued in dark mode

Beyond that I haven’t used R3 for anything. I’m still seeing too many odd bugs being reported to make me comfortable moving any client projects to it. So I’m still using 2019r1.1 – basically the last version I contributed to 🙂

In the mean time I have managed to assemble lists of differences for various project types. These are all the differences I can discern between 2019r3 and 2019r1.1

macOS Console 64 bit

macOS Web 64 bit

macOS Desktop 64 bit

iOS 64 bit

I’ll see about compiling lists of differences on Windows & Linux as well

Note that this is changes and may simply indicate that some reorganization has taken place. For instance the HTMLViewer appears to have had many events removed but it appears the code is simply reorganized so that event handlers, for instance, are not handled in a Xojo stub and re-raised but are raised directly by the HTML Viewer plugin.

EDIT – I can see that I’ll need to update how this data is presented to make situations like the event handling on the HTMLViewer more clear. It appears that the old HTMLViewer had event handlers and event definitions so the HTMLViewer would handle the event and re-raise it so you could handle the event. This appears to have been reconfigured in 2019r3 – so the event is no longer handled by the HTMLViewer and re-raised but just not handled at all so the base class event can still be handled. To the end developer this change is invisible but in the overall framework set up it is readily apparent which is why my 2019r3 differences list includes the removal of all these events.

Overloading

No not your plate (despite it being right around American Thanksgiving)

Sometimes when you write your code its convenient to have several versions of “the same” method.

For instance, in Xojo you might look at the AddRow method on the Listbox class )in 2019r1.1) and see that it has several forms

ListBox.AddRow(ParamArray Item as String) 
ListBox.AddRow(items() as String) 
ListBox.AddRow() 

This is a great example of “overloading” – having one method with many different signatures. Each is unique and distinct from the others and the compiler doesn’t have to do conversions that might lead to ambiguous situations when you pass several strings to the method.

The same can be said for the classic Date class. It had several constructors like

Date.Constructor()
Date.Constructor(CopyDate as Date)
Date.Constructor(Year as Integer, Month as Integer = 1, Day as Integer = 1, hour as Integer = 0, minute as Integer = 0, second as Integer = 0)
Date.Constructor(Year as Integer, Month as Integer = 1, Day as Integer = 1, hour as Integer = 0, minute as Integer = 0, second as Integer = 0, GMTOffset as double)

Note the last two are VERY similar but vary in the very last parameter.

And you can also do this in your own classes & code.

You could easily add many constructors to your classes so you can create instances using a wide variety of parameters.

As long as each overload can unambiguously be called the compiler wont have any trouble with things.

Its usually the “unambiguous” part that gets people into trouble as they defer to using default values for parameters. For example, if I have the following class along with the constructors shown you may find you have issues – but only sometimes

Class TestClass
   Public Sub Constructor()
   End Sub
   Public Sub Constructor(foo as integer = 0)
   End Sub
End Class

If later I have code like

Dim c As New TestClass(1)

This will work without issue since TestClass only has one possible constructor that matches that signature. So things compile & run fine.

However if later I try to do

Dim c As New TestClass

I will now get a compile error saying

Window1.Open, line 1
There is more than one item with this name and it’s not clear to which this refers.
Dim c As New TestClass

The compiler cannot figure out whether I mean to call the constructor with no parameters, or the one that has a single parameter with a default value that I simply have left out. And so it gives up trying and you get a compile error.

Once you realize that the issue is that the compiler doesn’t know which method you meant you can address the problem. Perhaps in this case a constructor with a default value for the parameter makes no sense and so you’d remove that default value. Or you decide that you really only need the Constructor with the single parameter and default value since you can deal with it as if it were the no parameter version.

Often when I’ve encountered this problem it is a symptom of having optional or default values that, when omitted, make one method have the same signature as the other.

Careful out there and try not to confuse the compiler too much.

Operator_Convert

Operator_Convert is a very handy method to implement on a lot of classes. It not only lets you create a mechanism to make your classes convert themselves into other types but it also lets you create new instances FROM other data types.

So let’s start with the simple forms of operator_convert – the “convert TO” forms.

Suppose you have some class defined called “myClass”

Class myClass
End Class

and you want to make it easy to have this class write log messages to the DebugLog. You most certainly could write a “ToString” method as an explicit way to convert this class to a String

Class myClass
   Function ToString() as string
   End Function
End Class

and then in your code you’d use it like :

dim instance as new MyClass

// lots of intervening code

system.debuglog instance.ToString

And maybe this isn’t so bad. It IS explicit which is most times a good thing. Your code will have a certain clarity to it because of this style.

But there is another way to do much the same thing that is also effective – despite it being slightly hidden and magical like a variants ability to automatically convert itself to other data types by assignment. And this “magic” is operator_convert

In a class like our sample

Class myClass
   Function Operator_Convert() as string
   End Function
End Class

And now your usage could look like

dim instance as new MyClass

// lots of intervening code

system.debuglog instance

Since System.Debuglog takes a string as a parameter the compiler figures out that our class has a suitable Operator_convert method and will call that for us.

You can define many operator_convert functions that convert TO other datatypes and as long as they dont cause any ambiguity you will get the results you expect. You may get an ambiguous situation of you define a Convert To operator_convert for Integer, Int32 and/or Int64 since Integer is simply an alias to one of those types depending on whether you are building for 32 or 64 bit. There can be others but this is the most common.

There is another form for operator_convert – the “convert FROM” form.

In this case operator_convert behaves in many ways like a constructor called with a parameter. However one thing to remember is that Operator_convert is NOT a constructor! Its an initializer at best. If your class depends on constructors being called make sure when you use the convert FROM form you call your constructor !

For our sample class suppose we want to initialize it from a string.

Class myClass
   Function Operator_Convert() as string
   End Function

   Sub Operator_Convert(initializeWith as string)
      // if we rely on the constructor having been called 
      // then call the Constructor here !
       
      // now set our class up from whatever data is in the
      // parameter passed
   End Sub

End Class

and we could use it like

dim instance as MyClass = "123"

// lots of intervening code

system.debuglog instance

Something to note is that these conversions can appear to be hidden away from a casual reader so use them with care and consideration. Often explicit code, like the ToString example above aids a reader in understanding the code because its right there in front of them that you are asking the class to give you a string representation for some purpose.

Keep that in mind and use these with that in mind.

Enjoy !

Using interfaces (again)

A recent comment on my post about overriding prompted me to write this second post about interfaces and why you might use them. Its clear to me that I havent done a very good job of explaining why you should or would use them.

In some languages you can create classes that inherit from one other and one other only. Xojo is this way. Some others let you inherit from several superclasses but this has a set of issues that Xojo avoids by limiting things to single inheritance. Java is also this way and does not support multiple inheritance.

So what do you do in the case you have a class you’ve created and you want it to “inherit” from multiple other classes ? Suppose you have a class that needs to inherit from “InputStream” so it can be read from AND also needs to inherit from “OutputStream” so it can be written to ? Xojo has such a class – BinaryStream.

The way to achieve this is actually NOT to try & inherit from two super classes but to make the InputStream and OutputStream into interfaces and then have your class implement both interfaces. In fact this IS what BinaryStream does – it implements both the Readable and Writeable interfaces so you can read from it and write to it.

You implement the methods on each interface and then any other methods on your code that takes a Readable parameter you can pass a BinaryStream to, since BinaryStream IsA Readable. And any of your code that takes a Writeable parameter you can also pass the BinaryStream to since it IsA Writeable.

As well you can extend interfaces just like any other class.

So its perfectly legal to write a method like

Sub DoREadableStuff(extends instance as Readable)

just as you would for any other type in Xojo.

This gives you a lot of flexibility in how you use & implement interfaces.

About the only thing you might run into is what to do if you have two interfaces that you want a class to implement and they have methods that you have to implement that are named the same ?

As long as the full signature of the methods, method name and all parameters, are unique this isnt a problem as you can implement both and you will just appear to have 2 or more overloads of the same method just taking different parameters.

But what if they have the same parameters ?

If you just add both interfaces then you will have to methods with the same name and the same parameters and Xojo will not compile your program any more because its ambiguous which one would be used when.

And this is where a little used aspect of Xojo comes into use.

Lets set up a small example so you can follow along as that will make things much clearer.

Start a new desktop project.

To the project add

  • a class named class1
  • a class interface named interface1
  • add a method to interface1 named Connect
  • a second class interface named interface2
  • add a method to interface2 also named Connect

Now we’re going to make it so class1 implements both interface1 and interface2. Click on Class1 and make sure the Inspector is showing. Click on the Interfaces button in the Inspector. Select both Interface1 and Interface2. I often also select the “insert #pragma error” in each method option at the bottom of the pane.

Click OK and empty stubs for all the methods in Interface1 and Interface2 will be added to Class1. And note we do have 2 connect methods.

If you try to run or analyze the project you will get a “duplicate method definition” error – this is exactly as expected since we have two identical signatures (method name and parameters)

And now we’ll fix this. What we need to tell Xojo is that “this method implements the Connect method from interface1 and this other method implements the Connect method from Interface2”.

Right click on the first Connect method. And select the “Show Implements” option from the contextual menu. Notice that when you do this an extra field shows up in the Inspector.

This extra field is used for exactly what we just stated – telling Xojo which Connect method each of the Connect overloads actually implement. So for the first one we’ll put in the field Interface1.Connect. Then click the second Connect method and in the field put Interface2.Connect

You’d think we’re done at this point because those two method now say which method from which interface they implement. However, they are still exact duplicates and the compiler will still complain about that. So rename the first one Interface1Connect and the second Interface2Connect. I’ve renamed this way JUST for clarity for this example. You could rename them anything you liked that doesnt cause other errors.

And now for the proof that this works.

In our sample applications Window1.Open event (or opening for those using 2019r2 and newer) lets put in the following code



Dim i As interface1 = New Class1
break
i.Connect

Dim j As interface2 = Interface2(i)
break
j.Connect

Recall that a Class1 IsA Interface1 because it implements that interface. And that it is also an Interface2 because it also implements that interface. If you run this code now you wont get any errors BUT it is hard to see that it is doing exactly what we’ve told it to.

If you run & step INTO each call to Connect you will see that because in the first case i IsA Interface1 that stepping into i.Connect does indeed call Interface1Connect – the exact method we said implemented the Interface1.Connect method.

And when you get to the second break statement and step into j.Connect you will see that, because j IsA Interface2 that this call to Connect will end up in Class1’s Interface2Connect method – the one set said implemented Interface2.Connect.