Object Oriented Programming (OOP) puts in our hands the ability to create apps in a flexible and powerful way. Xojo embraces that philosophy in the Xojo language itself, allowing us to implement code in a flexible way for reuse, extension and maintainability that reduces the development cycles. One of these language tools is, in fact, common in other low level programming languages: Casting or type conversion. If you are interested in this (and you should be), continue reading and discover what it is, why you should be interested in it and how can you use it in your next Xojo app!
If you are using Xojo already, or any other programming language, then I’m pretty sure you are using casting without even noticing it. For example, when you use simple types like Double or Integer, or even when assigning a String value to a Text variable. In these cases, everything happens behind the scenes. For example, these could be some type conversions you made in a regular basis:
Dim n as Double = 10.20 Dim i as Integer i = n // The 'i' variable will have the value 10, losing the decimal part as result of the implicit conversion process Dim s as String = "Hello World!" dim t as Text t = s.ToText // Both variables have the same text using the "ToText" method in order to convert it to the expected type by the target variable.
Both cases shows implicit conversions. This is, these are done without your intervention. However, in other scenarios we need to make these explicit, like when we need to use an object as if it was an instance created by the parent class in the hierarchy, and using it in a later step as a member of its real subclass (child class in the hierarchy), so we can continue using their methods and accesing the properties declared under that class.
Why would you want to do something like this? Well, there are a couple of cases that just jump into my mind:
- When it comes to objects created by classes that are not directly connected through the class hierarchy, but that share one or more common Class Interfaces.
- When these are objects created by several subclasses, descending from a common parent class.
For the first point, it would be the case where we need to maintain a collection of the same kind of objects, probably defined by a Class Interface type, but that in reality are created from several classes. This way, we can put all these objects in the same collection, iterating them and sending to them any of the methods defined by the Class Interface.
Something similar is what happens with the second scenario, where we can access to the common properties and methods offered by the parent class and, thus, shared an availables too in the instances created from their subclasses.
In fact, it is very probable that you are already using this second scenario in your projects as when you iterate all the controls (parent Class Control) put in the layout of a particular Window instance, a WebPage or an iOSView (each platform has its own parent class for controls). Here is a code example (in this case
me refers to the
Window instance where we put our code):
For n as Integer = 0 to me.ControlCount - 1 StrBox me.Control(n).Name Next
Showing this way the name of all the Window controls, no matter if they are TextFields, ListBox, PushButton, etc. After all, these controls classes are inherited from the Control class. Thus, the previous code snippet also could be written like this:
Dim c as Control For n as Integer = 0 to me.ControlCount - 1 c = me.Control(n) MsgBox c.Name Next
But, what happens if we just are interested in showing the name of the controls from a specific subclass? For example it could be the case where we just need to show the name of the TextField controls used in the window layout. All the instances maintain internal information about themselves, like their Type, so we can access to that information during the execution of our apps through the introspection mechanisms provided by the Xojo language; but if we just need to check an instance type, then we can simply use the IsA operator. This operator allows us to compare an instance against a Class or Class Interface, returning a boolean value as result of such comparison. Then, we can use this fragment to show the name of the TextField controls used in the window layout:
Dim c as Control For n as Integer = 0 to me.ControlCount - 1 c = me.Control(n) If c IsA TextField Then MsgBox c.Name End If Next
Casting in action
When we work with an instance as if it was an instance from the parent class, or as a member of a Class Interface, then we call it Downcasting; something we could translate as going down in the class hierarchy. For example, this is what we have done in the previous fragments, where we use all the controls of the user interfaces as if they where instances from the Control class.
As we go deeper in the class hierarchy, we reduce the amount of properties, methods and events we can access. I mean, we are limiting ourselves in the functionality achievable by the instances. This is something we will be glad to embrace if we take into account the benefits that this practice gives us in return as flexibility and code cleanness.
Nevertheless, and continuing with the same example, what if we would want to retrieve all the TextField instances, not as Control instances but as their own, original, class type in order to access their defined properties or methods? How can we accomplish that?
Let’s say that we don’t just want to show the TextField instances name, but also change their background color, something that is not implemented under the Control class. That is, we need to use some behaviour specific to the TextField class. Here is where Casting comes into play: the ability to cast or project a class instance as the type we want it to be:
Dim c as Control dim t as TextField For n as Integer = 0 to me.ControlCount - 1 c = me.Control(n) If c IsA TextField Then MsgBox c.Name t = TextField(c) // Casting from the "Control" instance variable as a concrete subclass: "TextField" t.TextColor = &cFF0000 End If Next
That is, in order to use the Casting feature in Xojo, we need to put between parenthesis the name of the instance we want to convert, preceded by the name of the class we want the instance to be converted to.
Notice that when we use this OOP mechanism, we will not be backed by the usual help provided by the compiler on type checking. This means that if, for example, we cast an instance to a wrong target class for such instance has not internal information (it has not been originally created from that class, subclass or does not implement that class interface), then probably your app will not work as expected and, very probably, will fail or crash during its execution. To prevent this, you need to check for the inner class of any instance using any of the language provided mechanism in order to make sure you’re casting to the right type.
Finally, we could simplify the previous code like this:
For n as Integer = 0 to me.ControlCount - 1 If me.Control(n) IsA TextField Then MsgBox me.Control(n).Name TextField(me.Control(n)).TextColor = &cff0000 End If Next
This way will loses some readability (code intention), but results in a more compact code.
Throughout this example we have seen how easy it is to work with instances as if they where more generic, and converting them again to their original type when we need to use their specialized behaviour or access their specific status, using the Casting OOP mechanism for that.
You can watch this video (en español) to see this in action:
Javier Rodriguez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages AprendeXojo.com and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others