So I had hinted at this topic before, but now that 2007r3 has been released, I can discuss it in-depth. Of course, had you come to REAL World this year, then this would be old hat to you since it was a part of my design patterns talk.
Friendship is a concept that other programming languages have which is a way for a class to expose their "private parts" to other classes. For instance, let's say that you have Class A and Class B which are sibling classes (not a parent/child relationship), but they work together very closely. If Class B needed to access a private method from Class A, then you need to make these two classes "friends." This does tightly couple classes together, but is still valid on some occasions in an OOP project. The other alternative would be to make Class A's method public, but then every class can access it, which is no good.
So how would you go about accomplishing this in REALbasic? Well, before 2007r3, the only way to do it was to make the method public. The trouble there is that Class A must now "support" that public method regardless of who calls it. Instead, we are going to do some magic steps so that Class A only has to support the method for Class B's use (which is a much easier maintenance burden).
We're going to couple a new concept with an old, unknown linguistic feature: namespaces and interfaces.
Namespaces are a way for you to put scoped items (like classes, modules and interfaces) inside of a module. So, for instance, you could hide a class inside of a namespace by placing the class into a module and setting its scope as Private. If you do that, then only other items in that namespace can access the private class.
Interfaces are a concept which most people are familiar with. They're a contract that says "this class implements these methods with these signatures." The unknown part is that you can satisfy that contract regardless of the method's scope. For instance, you can satisfy the contract by using a private method.
So let's put these two concepts together to create a friend pattern in REALbasic.
Put Class A and Class B into Module1, and make them global in scope. This means that anything can use Class A and Class B. Make an interface into Module1 and make its scope Private (so that it cannot be accessed outside of the Module1 namespace). Class A should implement the interface. Now you've effectively set up the friendship pattern. You may wonder how that is, so I'll spell it out a bit more.
Since Class A can implement the interface with private methods, that means that anything with a reference to Class A cannot see the private method. But anything with a reference to the interface *can* see the method because interface methods have no scope! So when Class B needs to call into Class A's private method, it does so by typecasting Class A to the interface type and call the method that way.
I've made a simple example project to demonstrate this concept here.
You may be thinking that this is an awful lot of work to get friendship support, and it is. However, it also allows you a very fine-grained amount of control over access to private parts of a class because you control the scoping of all the parts involved.
I hope this makes sense -- it was typed up while listening in on a long meeting, so it may come across slightly scatter-brained. ;-)
Thanks for spelling it out, Aaron.
To be honest, I think you dropped just enough hints to give us the tools to work it out for ourselves.
One question. Will these design pattern talks ever be available to us who were not at REALworld ?
I honestly have no idea -- You'd have to contact someone like Dana to find out for sure (dana@realsoftware.com).
Isn't this a rather devious way to add "friend" capability? Seems to me that each class should have a property called "Friend/s", a la the one for implemented Interfaces.