Hiding your insides from the rest of the world

Xojo has no “friend” scope (see https://www.ibm.com/support/knowledgecenter/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/cplr044.htm)

In other words there is no way to indicate that one class or method can call the protected / private methods of another class. Either the methods are public, and any other code can use them, or they are protected so only the class & subclasses can use them, or private and then only that class can access them.

Sometimes you want “friend” so other classes in a related set of classes can call the protected methods of the other classes in that same set.

I know this all sounds a bit theoretcial but imagine you write a PDF Document Class. And that PDF class has other classes that make up the contents of the PDF – things like PDF Page, and PDF pages might have PDF Text Objects, PDF Graphic Objects, etc

And there could be reasons that a PDF document needs to be able to use methods from PDF Page – but you dont want those methods exposed to every other bit of code in anyones project.

So how do you hide those details from code ?

If all you do it put all the PDF classes ina folder in Xojo then that wont suffice. Folders have no effect as far as the compiler is concerned.

What if you put everything in a module and make all the classes in that module global ?

That would still leave every public method usable and callable by any code.

But, here’s the trick. You CAN put an interface inside the module.
And that interface can be PRIVATE. This means that ONLY classes and code IN the module can access that interface.

And, since interfaces CAN be satisfied using PRIVATE methods you CAN then implement the interface with private methods.

When you combine these two things you get a way for all the classes & code in the module to call the private methods of the classes in the module by casting to the private interfaces and NOTHING outside the module can access them because they can use the private interface, nor can thy directly call the private methos of the classes.

“Friend” scope might still be nice though

The technique outlined only lets you handle hiding within the scope of a single module and if you needed this to work between two separate modules you’re unlikely to find quite such an elegant solution.

Friend would make that much more possible.

Feels good

Took a few minutes last night and helped out another member of the Xojo world.

Seemed like he was a bit stuck and what I pointed out got them back on track.

And then I got several messages :

Norman, you are a FUCKING treasure to this community.

Nobody tries to help as much as you do.

Nobody I’ve ever worked with.

I wont name names but it IS nice to get feedback like this 😛

Recent ski trip

Recently my wife and I took my mom with us when we went on a ski trip.

While there I came across a couple guys who were paragliding and it looks like so much fun!

Maybe next year I’ll give this a try 😛

dim Session as Session = Session

Theres a long thread on the Xojo forums about Color shouldnt be a reserved property name

It really isnt. This is JUST the IDE preventing you from using the name IN the IDE

It causes no confusion.

The title of this article was, at one time, a recommended way for figuring out the current session in a Web 1.0 app

The compiler has NO issue sorting out whats a variable, whats a data type, and whats a method call.

In the code from the title it knows that :

  1. the first session following the dim MUST be a variable name (it cannot be a method call, property, constant or data type in that position)
  2. the second dim following the AS MUST be a datatype. It cannot be a variable name or method call, or property or constant etc
  3. and the last session, following the =, cannot be a data type. So it MUST be either another variable name OR method call. Since this line is just not defining this variable it cant be a usage of itself and that leaves ONLY a method as a possibility.

The compiler gets it right.

And you can see that it does if you :

  • start a new desktop project
  • add a new class and name it Foo
  • add a shared method to Window1, named foo() that returns foo
  • now add a property to Window1 named foo as foo
  • the in Window1.Open simply put this one line of code
self.foo = Foo

self.foo refers, int this case, to the PROPERTY (since there is no method that could possible be called – there is not assigns version that might cause ambiguity)

The Foo after the = has to be either a variable or method; Xojo’s preference is to call the method before trying to use a property

Now, would I recommend using the name of an existing data type as a property ? In general no but there are cases where it makes perfect sense.

Suppose to have a class that represents a run of text that all has the same type. Its a consistent type face, size, italic, bold etc and one of those properties on such a thing could reasonably be “Color”.

Many have suggested calling it something else for clarity. But that might actually BE the most accurate name for it. For instance Xojo itself has such a data type but they use the name “textcolor”. Color would actually be a suitable name here.

Here’s a sample project that does exactly this and has NO issue

EDIT : You can even write as one line in 2020r2.1

dim color as Color = Color.RGB(230,198, 178)

No confusion arises compiling this line (there may be ancillary issues with other code but COLOR isn’t “reserved” to ONLY be a data type name.

Big Sur and 2019r1.1

The official line is “if you want to run Big Sur you MUST use a version newer than 2019r3.2” – at least for desktop apps (web apps arent affected in the same way)

But you CAN actually get 2019r1.1 to work for desktop apps on Big Sur

Here is what I have done to be able to run Xojo 2019r1.1 on Big Sur (Intel) – and to successfully DebugRun and Build Desktop applications:

Replace these files in the Xojo 2019r1.1 application bundle with those from 2019r3.2:

Contents/Resources/SDKStubs/macosx10.14/System/Library/Frameworks/AppKit.framework/AppKit.tbd
Contents/Resources/SDKStubs/macosx10.14/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit.tbd

Numbers

Closed (Already Exists) – 6
Closed (by Design) – 38
Closed (Duplicate) – 32
Closed (Misc) – 25
Closed (Not Actionable) – 3
Closed (Not Reproducible) – 38
Closed (Won’t Implement) – 7
Fixed – 5
Fixed & Verified – 91
Implemented – 2
Implemented and Verified – 9
Needs Review – 6
Reproducible – 141
Resolved – 2
Reviewed – 189
Verified – 29

Open – 365
Closed – 259

Operator_Lookup

In code I’ve been writing I’ve found a need to be able to “add properties” – but not in a conventional way.

Normally I’d just add a property to some class in my Xojo code and be off & running. But now I’m needing to be able to define “classes” (They’re not really classes) in a way that they can be added EVEN AFTER the application has been compiled.

So this means I need to be able to added to a text file, that gets read, and a new “property” is available on the “class”. Admittedly a very unusual need.

But this IS possible.

There is a little used method that any class can use to make it so the compiler can “lookup” something that is not defined in the conventional ways. That method is _operator_lookup_. By adding this method to a class the compiler will call it to lookup any “name” on a class that it cannot find using its normal mechanisms. Note that this WILL make it so you no longer get compilation errors. So IF you use operator_lookup you need to make sure you have a means to debug any errors (like a break statement or something in you implementation to catch any typo’s)

With those warnings out of the way how can you make use of this ?

In normal code you might never need to.

However, if you suppose you have a class that is dynamically configured and used like the following :

for each configProperty in classInstance.Configuration
    // now use this property in some generic way 
    // maybe like an inspector that can edit anything 
    inspector.EditProperty configProperty
next

Then its possible you can add a configuration property that can be manipulated in a generic way and you DO NOT know all of them ahead of time.

Operator_Lookup lets you deal with this.

And it can be both a GETTER and a SETTER.

You’ll find some sample code in a series of posts I made about this topic

API 2 speed hit

I’ve seen others comment that they’ve run into slow downs with API 2.

I’ve been trying to sqeeze every last ounce from a large app and ran into this one. I’d suspected it might be a hit but measuring it indeed shows there is a hit – not tens of seconds but when you want EVERY last microsecond these few add up.

My test code is the following

Const kNumberOfIterations = 1000000

Dim startTime As Double
Dim endTime As Double

startTime = System.Microseconds

For i As Integer = 0 To kNumberOfIterations
  
  Dim s As String = Trim( "abc" + Str(i) + "def" )
  
Next

endTime = System.Microseconds
System.debuglog " elapsed 1 = " + Str(endTime - startTime, "###########0")

startTime = System.Microseconds

For i As Integer = 0 To kNumberOfIterations
  
  Dim tmp As String = "abc" + Str(i) + "def"
  Dim s As String = tmp.Trim()
  
Next

endTime = System.Microseconds
System.debuglog " elapsed 2 = " + Str(endTime - startTime, "###########0")

Pretty simple operations but when I run this compiled with default optimization (aggressive doesnt work in the app I’m building for reasons I have yet to discern) I get the following results

Feb 11 22:22:52  My Application[46161] <Warning>:  elapsed 1 = 557024
Feb 11 22:22:52  My Application[46161] <Warning>:  elapsed 2 = 573987

A different of roughly 20,000 microseconds (2 msec)

In a small app that I can compile as aggressive this difference shrinks – but as I noted I cant use aggressive with my app yet.

That API forces you to create & use more temporary variables can have an impact. Sticking with the API 1 equivalent _may_ save you time.

More old things relearned recently

I know this was posted about years and years ago. Its probably been a decade or more since this was last written about.

But I ran into it again and had to say to myself “Oh right you cant do this this way because the App method will return nil at this point”

The situation is I wanted to put a custom menu item subclass into the menu bar. This works. You can add the item and change its super and all your constructors etc will get called. But if you need to refer to “the application” then there are times when it will NOT work. Like if the item you added is part of the default menu bar created when the application starts up.

At that point the global App method can and may return NIL because the default menubar is created BEFORE the application singleton is registered in a way the App method can return it.

So IF you need to do something like this and need to refer to “App” then you may need a flag that delays this initialization until some time after the app has started up and you CAN get a valid reference to the singleton.

Heads up !

Convert To or Convert From ?

A while back I started thinking that some of the new style Xojo is using is awkward but it never really struck me why it felt that way.

After working with new releases for a while I know what I find strange.

Sometimes you tell an instance to do something.

var someInteger as Integer
var s as string
s = someInteger.ToString

for instance tells out integer instance someInteger to convert itself to a string. THe style is very much object verb.

Except when its not

var someStringArray() as String
var s as string
s = someStringArray.ToString // NOPE - this does not compile

No in this case we do not tell our “object” , the array, to convert itself to a string like we do many other things. In this case we have to tell the String “type” to make a string From an Array

Var someStringArray() As String
s = String.FromArray(someStringArray)

Yet there are many other places where ToString does exist. Here’s a handful in the Language reference.

Thats not to say the “From type” conversion doesnt make sense. There are lots of places it does. For things that have constructors i makes sense that the “convert from” method might be a constructor, or maybe a shared factory method that returns a new fully created instance. Or maybe its the operator_convert initializer that can return a fully constructed instance. I had a long discussion with Aaron about whether a constructor vs factory vs operator_convert makes more sense and there are some interesting considerations he brought up but I wont go into those details here. Maybe another post another day.

For intrinsic non-reference types like Integer, string, boolean etc where there is no means to use a constructor the choices are really limited. But even in that case we see that things like booleans, integers, colors etc have both a ToString and FromString – something arrays do not have.

That seems particularly inconsistent with all the efforts Xojo is going to to make the language more consistent.

And now I know why I find it jarring that its missing for arrays to be able to tell them to convert To String.

Later !