Who defined that ?

Sometimes its nice to be able to know what class defined a property or method. Introspection makes this mostly knowable.

The reason I say “mostly” is that something the introspection metadata does not tell you is if the property definition is local or inherited. So you cant tell for sure if a property in a subclass is one defined in the subclass or the inherited one from the superclass. It would be nice if this were knowable and introspection told you this but I’m not holding my breath that this will be altered as its been this way for a long time.

So lets see what introspection _can_ tell you as sometimes that is sufficient. And for when its not well you’ll have to sign on to a feature request to add metadata to introspection so you can tell.

One thing to know about introspection is that for a subclass you also get all of the supers information. So when you get the list of properties in a subclass all the supers properties will be included in that list as well.

We’ll make use of that tidbit.

For we need to get the TypeInfo for the class of interest. We’ll focus on doing this with something simple to start with – a Window. If you put this code in the open event of a Window you will get the TypeInfo for the window this is in.

// get a list of current class up through all its supers
dim current as Window = self
Dim t As Introspection.TypeInfo = Introspection.GetType ( current )

The TypeInfo is the metadata that tells you

  • the class’ name
  • if its an array, class enum, interface, or pointer,
  • if the item is a primitive type like an integer, color, or double
  • if its public or not
  • if the item is a value type or not (yes I wrote that article too)

This is all handy info. In addition to telling you all this the TypeInfo item is the one that allows you to access the properties, methods, attributes, and constructors of a class. There are several methods on the TypeInfo instance you can call that gets you a list of items you can then use.

To access the list of properties you call the GetProperties method of the TypeInfo instance

Dim props() As Introspection.PropertyInfo = t.GetProperties

Note you get back an array of PropertyInfo instances. Since any class might have more than one property this makes sense. An array is useful.

If you put a break point on the “Dim Props” line and ran this code you could manually see whats in the Props array. For a Windows you’ll have a length list and it will include things like Handle, Top, Left, Width and all the properties you might expect to see. And for each PropertyInfo object you see whether the item is private, public, protected, computed, readable and writable, shared and another object that tells you about the type of the property.

Introspection if full of objects that use other objects to tell you more information.

Again, this list doesn’t tell you anything about where the property originated – whether its defined IN this class or inherited from a super class.

So to keep track of where the property “originated” as best we can we’ll need to go through this list and mark every property as “from this class”. Then we’ll move up to the super class, get its list of properties, mark all of the ones we already knew about that match, by name, as being from the superclass. And then repeat this until we get all the way to the point where we are at the very base class that has no super.

For Window this is easy as Window has no super

We’ll create the code to do a window and then extend it to do a class that does have a deeper hierarchy of supers.

Start a new desktop project.

Add a listbox and pushbutton to the Window. Make sure the listbox has 2 columns.

Then create a new method on Window1 – GetSuperPropertyList( w as window)

In there lets put code similar to what was mentioned above.

// get a list of properties on Window
Sub GetSuperPropertyList(current as Window) 
  Dim t As Introspection.TypeInfo = Introspection.GetType ( current )
  Dim allprops As New dictionary
  Dim props() As Introspection.PropertyInfo = t.GetProperties
  For j As Integer = 0 To props.ubound
     Dim oneProp As Introspection.PropertyInfo 
     oneProp = props(j)
     listbox1.addrow t.name, oneProp.Name
  Next
End Sub

We start by getting the TypeInfo for the Window passed in. And then from that we get the list of properties on a Window and put those in a listbox.

In the pushbuttons action event put

GetSuperPropertyListCount( self )

And run.

Press the pushbutton.

You should see in the listbox a list of about 30 or so items. In the first column everything will say “Window1” and the second column are the names of all the properties on a Window.

Quit the running application.

Lets adjust the code so it can handle more than just a Window.

Fortunately this change is quite simple. Every object type in Xojo inherits from “Object” and so we can pass ANY class instance to a methd that uses “Object” as the type of the parameter.

Change the declaration of GetSuperPropertyList from

Sub GetSuperPropertyList(current as Window) 

to

Sub GetSuperPropertyList(current as Object) 

And now in the pusbutton’s action event you can write

GetSuperPropertyList(self) 
GetSuperPropertyList(me)

Run and again press the button. This time you see a listing of the Window’s properties (self) and one from the pushbutton (me).

Now the only trick is to make the method list the properties of the immediate class and those of the supers. In order to do that we’ll need to :

  • go through the current class and make note of the class name and property name
  • get the super class
  • go through its properties making note of the class name and property name
  • lather rinse & repeat until we get to the point there is no super class any more
  • print out the list

Now as we go thought teach class and its super we want to note the property name and the class name, and then when we go through the super if the property exists we need to alter the name we recorded. A perfect place for a dictionary.

So lets alter the code to

// get a list of current class up through all its supers
Dim t As Introspection.TypeInfo 
// get the type info for the current item
t = Introspection.GetType ( current ) 
// a place to keep all the property info were about to gather up
Dim allprops As New dictionary

// as long as we have a class' typeinfo
While t <> Nil
  // get all the properties on the class
  Dim props() As Introspection.PropertyInfo = t.GetProperties
  // and save them in a dictionary
  // using the NAME of the property as the key
  // and the name of the class we founf it in as the value
  For j As Integer = 0 To props.ubound
    Dim oneProp As Introspection.PropertyInfo 
    oneProp = props(j)

    allprops.value( oneProp.Name ) = t.Name
  Next

  // get the immediate superclass of the class we're looking at now
  t = t.BaseType
Wend

// now we have a dict fill Of keys (propNames) 
// And values (the Class the define the prop)
// so list them all out
For i As Integer = 0 To allprops.Count - 1
  Dim key As String = allprops.Key(i)
  listbox1.addrow allprops.value(key).stringValue, key
Next

You can see that what we have added is code that does what we were doing before (getting the type info then the list of properties) and simply saves that list in a dictionary.

The thing that makes the code walk “up” the class hierarchy is the line

// get the immediate superclass of the class we're looking at now
t = t.BaseType

Every TypeInfo object knows which one is its superclass – this is the BaseType. And by using the BaseType each time in the while loop we move from the current type to its super type and so on until there is no super type.

In each iteration around the while loop we update any existing properties to say they cam from the super type (see note above about not being to actually tell if this is true or not). For most purposes this is adequate.

If you run this now & press the button you will see that instead of just Window & PushButton we see a bunch of properties from Control & RectControl. These are from the superclass of PushButton.

And there you go. A handy method to walk up the hierarchy and get which properties came from where.

Follow up on why shadowing should be avoided

Shadowing is usually a bad thing. But you can “sort of” do it right as I explained previously. I say sort of because there are some gotcha’s – one of which I’ll explain here.

However, there are still gotcha’s that can’t be worked around. Some of them are because of how the Xojo framework does things. Like control locking.

You’d think that for locking purposes the framework would set the instance’ left, top, width and height and, if properly shadowed, the instance computed properties would get set and they could pass the change along to their super class and voila everything would be happy.

In a perfect world this would be the case. But that doesnt appear to be how the framework does locking and so when you DO shadow a property like left, top, width or height the framework appears to cast everything to be a RectControl and sets whatever underlying properties it has thereby bypassing whatever shadowing you have so neatly set up.

And what you get is an issue like in this thread. Its unfortunate as shadowing would be a ton more useful if things like this worked by setting the instance’ properties.

Now, setting up shadowed properties “right” is a more advanced topic but if you’re doing this then you really need to understand what you’re doing and how to not make a mess.

But if it worked as I described above it would be super useful.

Handy Method Editor tips

Did you know that you can write, in the declaration pane for the method editor, the entire declaration and the editor will rip it apart for you ?

So instead of having type the name, tab, parameters, tab, return type, tab, select a scope you can type

Private Foo(i as integer) as string

and press tab or return and it will all get split into the right spots.

Like this

Press Enter and get

EDIT : FWIW you can do this in a property as well that isn’t a computed property. But not in a constant (yeah you can probably blame me for that)

Friends

When you design classes you often make the properties they hold private or protected so outside code cant mess with the innards.

But what if you want to allow that – sometimes ?

This is the notion of a “friend”. Another class that you can literally say “yeah its ok I know them and it’s OK if they mess with my innards as they are my friend”. Xojo doesn’t have such a notion. So how do you make this possible ?

First off you really need to think hard about what it is you want to do and do you really need “friend”liness ? You may not. An interface or some other mechanism may be more suitable.

But if you do some to the conclusion you DO need a “friend” then you can make one using namespaces and private interfaces.

What you CAN do is

  1. take your class (call it AllowFriends) & put it in a module
  2. declare a PRIVATE class interface that class AllowFriends implements since you CAN implement an interface with private methods.
  3. Add classes to this module that you want to make friends of class AllowFriends
  4. on each class that wants to allow “friend” access implement the interface with PRIVATE methods.
  5. now anything in this module, classes or methods, that is a friend of class AllowFriends can cast it to the private interface & access whatever you exposed in that interface – this WILL only be methods but since you can make method pairs act like a getter/setter things should be fine.

And now you have classes in that module that can be “friends” but nothing outside the module can be since they cannot access the private methods on each class OR the private interface. The interface is restricted to only be used by classes & methods that exist in the module.

It’s not exactly “friend” from C++ but its about as close as you can get in Xojo.

Handy tip for Enums

Ever tried to copy an enum from some outside source like Apple, MSDN, etc and wanted to retain the comments they have about each value in the enumeration ?

You can !

Enum values can have comments in them like

Public Enum ConnectionOption
 adConnectUnspecified = -1 //    Default. Opens the connection synchronously (after).
 adAsyncConnect    = 16 // Opens the connection asynchronously (before).
 End Enum

Simply edit each value in the enum and make sure you put one of the valid comment markers in the value line and you can have commented enums.

Enjoy !

Stupid IDE tricks

A question was asked the other day about “how can I list just all the Windows in my application” And that reminded me of something I added to the IDE some time back.

Advanced filters in the find field above the navigator. It has only a very short mention in the IDE user guide.

So if you want to find all the Windows in your application you can type something like this into the filter field

% type:Window

and press enter and you will see all windows and container controls listed (containers are window like objects hence why they are listed). You can use the type filter with just about any type you can imagine in your project; property, constant, enumeration, delegate, method and so on.

You can also put things in the type field that include wild cards. So if you want to see all properties, computed and regular, you can put

% type:%property

This will list any computedproperty or property, regardless of its name, in the navigator.

Combine this with a decent naming convention and you can make the filter work for you in a lot of ways I think a lot of people do not realize exists.

Exceptions vs error codes

This isn’t just a Xojo debate. API 2.0 is reported to use exceptions rather than error codes.

And I’m sure that once preliminary releases of a version with API 2.0 are out that this debate will start in earnest.

Personally I’ve used both. The biggest difference with how I’ve used exceptions in the past in other languages was their built in support for “checked exceptions“. I’d love to see this in Xojo as it makes it so the compiler can at least help you out by giving you a compilation error when you haven’t thrown or caught an exception that you must.

Something like this makes it much easier to track down how an exception propagates since every called method MUST declare it in one way or another. They cant just silently say nothing.

However I doubt Xojo’s compiler guy(s) would add it.

There are some great articles that argue both for and against exceptions and error codes. They are great reading and they are persuasive in both directions.1

But, for my money, if Xojo is going to move to exceptions, checked exceptions would be my preference simply for the clarity it adds.

  1. reading links

Error codes vs exceptions critical code vs typical code

https://blogs.msdn.microsoft.com/oldnewthing/20050114-00/?p=36693

Update on the “sometimes” constructor

In a previous post I showed how you could create a constructor that a layout could use but no other code could.

Seems that in oder to make this a little more generic and cross-platform you need to look for a different stack entry.

Because macOS and Windows do things differently you can get a very different stack trace on Windows that you would on the Mac. So instead of looking for Window.__Init%%o you should look for the substring ._CreateControls0%%o<

So the updated code in the no parameter constructor looks like

Try
  Raise New NilObjectException
  
Catch noe As NilObjectException
  Dim stack() As String = noe.Stack
  
  // IF this is an instance created on a layout we should find a 
  // ._CreateControls0%%o< in the stack above the call to this
  // Constructor
  // cant look for the whole string as parts of it are the specific  
  // name of the window being constructed which will change by  
  // window name

  For i As Integer = 0 To stack.Ubound
  If stack(i).InStr("._CreateControls0%%o<") > 0 Then
    #Pragma BreakOnExceptions default
    
    Return
    End If
  Next
  
  // and if we do not then raise an UnsupportedOperation error
  Raise New UnsupportedOperationException
End Try

Learning HTML is not the same as learning to write software

At least IMHO they are not equivalent. Why not ?
Html is a design markup language. One focused on layout and presentation. A web designer might use Adobe DreamWeaver to create the specific layout and look of a web site. And never touch a line of PHP, C, Javascript, or whatever language is used to implement the functionality of the web site. Wikipedia points this out on the first line of its entry about HTML where it says

Hypertext Markup Language (HTML) is the standard markup language for documents designed to be displayed in a web browser.

https://en.wikipedia.org/wiki/HTML

Conversely the developer writing the functionality might never touch a single line of HTML or CSS code to make the layout look any particular way. Layout and design are not necessarily their role.

There are however people who are conversant with both the design language (HTML) and add ons to it (CSS) as well as with certain programming languages that can be used on the Web (Javascript). Usually these are in the “front end” or the Web browser. And it’s not unusual to find someone who understand all of these.

Now there are even people who understand all these technologies that are used in the browser and all the back end technologies used to implement the additional functionality of a web site. Usually they’re known as “full stack developers“.

A person like this has learned the language of web designers, generally html and css, some programming languages, php and javscript are common, more than likely some web based framework for various controls and layout like jQuery or Angular, and usually has some knowledge about databases like mySQL or postgresql for the back end.

EDIT : 12:47 I’ve received a comment offline where a confused reader seems to think I implied that one is more important than the other. I make no claim one way or the other and, in software, they both play an important but different role. An ugly app is an ugly app. And one that doesn’t do what it says just doesn’t and so both are required whether its a successful app, web app, or web site.

We expect

Very useful words to keep in the communication between any company and its customers. Its not a promise. Just a rough outline of what things you are planning to do.

Some companies use phrases like this to let their customer base know “hey this is what we think we are going to be able to deliver” without having to promise a specific quarter or date. Sometime things don’t work out as you planned (Airpower anyone ??)

But stating something like this is useful for helping customers understand product direction and what things are more important than others. If you don’t plan to ship something for years then don’t say anything about it until it has a reasonable prospect of being in a shipping product within the next year.

Now there’s ALWAYS the implied “oh but things could come along that waylay our plans”- and that’s the beauty of “we expect to”. Its NOT a promise like if you had said “and it will be available in October”. This is very definite (will) and a promise of when (October).

Googling “microsoft says it expects” or “apple says it expects” you will find a lot of articles that have this phrase in them. These huge companies use this kind of talk all the time to set expectations. And for any company setting & managing expectations is a big deal.

*Edited to correct typos