On 16 Jul 2009, at 14:53, Richard Frith-Macdonald wrote:
On 16 Jul 2009, at 14:37, David Chisnall wrote:
On 16 Jul 2009, at 14:23, Jamie Ramone wrote:
I'd like to chime in here and say that this approach IS actually a
good idea as :
1 ) it does solve the ABI change breakdown problem and
Except that it doesn't, it just hides it. Now people subclassing
and referencing variables in the superclass need to explicitly
cast a pointer to a structure. If this structure changes, they
need to manually update their private copy of the ivars and if
they don't thing break in exciting ways.
No ... people subclassing NEVER reference any variables of the
superclass, because the superclass only contains a single instance
variable, and that's declared @private. Because the superclass
only ever contains the single instance variable, it never changes
with impementation details, and the ABI doesn't change.
2 ) it is actually much easier to read because it's a prime
example of
encapsulation and abstraction, so complexity is hidden.
It is not easier to read, because now you need a separate
structure definition, every ivar access has to go via a macro
which will look something like this:
#define ivar (((struct private_ivars*)_private)->ivar)
Actually it's
#define private ((PrivateClass*)_private)
Then
private->ivar = ...
Which can easily be converted to 'self->ivar' or just 'ivar' by a
global replace when we want to change because we have non-fragile
ivars available.
Thinking about it, this is actually very short/easy to do with the
preprocessor to support both gcc and clang (though I think we'd need
to comment it well) ...
eg.
#if clang
#define private self
@interface MyClass
{
#else
#define private ((MyClassPrivate*)_private)
@interface MyClassPrivate : NSObject
{
@public
#endif
// instance variables here
}
@end
#if !clang
@implementation MyClassPrivate
@end
#endif
@implementation MyClass
- (id) init
{
#if !clang
_private = [MyPrivateClass new];
#endif
// ivar initialisation here
return self;
}
...
@end
So if we are building with clang then we use non-fragile ivars, but
if we are building with gcc then we use the private class instance
to store our ivars.
To make it even simpler when using the same model repeatedly, we
could use macros and end up writing code like this:
GSBEGINPRIVATEIVARS(MyClass)
int var1;
char var2;
GSENDPRIVATEIVARS(MyClass)
@implementation MyClass
- (id) init
{
GSCREATEPRIVATEIVARS(MyClass)
...
return self;
}