Add mechanism for gdl2.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29866 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2010-03-07 13:35:07 +00:00
parent f59ba481f0
commit 026d6fc751
3 changed files with 114 additions and 24 deletions

View file

@ -1,3 +1,11 @@
2010-03-07 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSObjCRuntime.m:
* Headers/Additions/GNUstepBase/GSObjCRuntime.h:
Add function to add 'overrides' as a form of programmatically
controlled category similar to behaviors, giving an app control
over the order in which methods are added to a class.
2010-03-05 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSCompatibility.h:

View file

@ -116,9 +116,66 @@ GSObjCMethodNames(id obj, BOOL recurse);
GS_EXPORT NSArray *
GSObjCVariableNames(id obj, BOOL recurse);
/**
* <p>A Behavior can be seen as a "Protocol with an implementation" or a
* "Class without any instance variables". A key feature of behaviors
* is that they give a degree of multiple inheritance.
* </p>
* <p>Behavior methods, when added to a class, override the class's
* superclass methods, but not the class's methods.
* </p>
* <p>Whan a behavior class is added to a receiver class, not only are the
* methods defined in the behavior class added, but the methods from the
* behavior's class hierarchy are also added (unless already present).
* </p>
* <p>It's not the case that a class adding behaviors from another class
* must have "no instance vars". The receiver class just has to have the
* same layout as the behavior class (optionally with some additional
* ivars after those of the behavior class).
* </p>
* <p>This function provides Behaviors without adding any new syntax to
* the Objective C language. Simply define a class with the methods you
* want to add, then call this function with that class as the behavior
* argument.
* </p>
* <p>This function should be called in the +initialize method of the receiver.
* </p>
* <p>If you add several behaviors to a class, be aware that the order of
* the additions is significant.
* </p>
*/
GS_EXPORT void
GSObjCAddClassBehavior(Class receiver, Class behavior);
/**
* <p>An Override can be seen as a "category implemented as a separate class
* and manually added to the receiver class under program control, rather
* than automatically added by the compiler/runtime.
* </p>
* <p>Override methods, when added to a receiver class, replace the class's
* class's methods of the same name (or are added if the class did not define
* methods with that name).
* </p>
* <p>It's not the case that a class adding overrides from another class
* must have "no instance vars". The receiver class just has to have the
* same layout as the override class (optionally with some additional
* ivars after those of the override class).
* </p>
* <p>This function provides overrides without adding any new syntax to
* the Objective C language. Simply define a class with the methods you
* want to add, then call this function with that class as the override
* argument.
* </p>
* <p>This function should usually be called in the +initialize method
* of the receiver.
* </p>
* <p>If you add several overrides to a class, be aware that the order of
* the additions is significant.
* </p>
*/
GS_EXPORT void
GSObjCAddClassOverride(Class receiver, Class override);
GS_EXPORT NSValue *
GSObjCMakeClass(NSString *name, NSString *superName, NSDictionary *iVars);

View file

@ -757,30 +757,6 @@ GSProtocolFromName(const char *name)
}
/**
* <p>A Behavior can be seen as a "Protocol with an implementation" or a
* "Class without any instance variables". A key feature of behaviors
* is that they give a degree of multiple inheritance.
* </p>
* <p>Behavior methods, when added to a class, override the class's
* superclass methods, but not the class's methods.
* </p>
* <p>It's not the case that a class adding behaviors from another class
* must have "no instance vars". The receiver class just has to have the
* same layout as the behavior class (optionally with some additional
* ivars after those of the behavior class).
* </p>
* <p>This function provides Behaviors without adding any new syntax to
* the Objective C language. Simply define a class with the methods you
* want to add, then call this function with that class as the behavior
* argument.
* </p>
* <p>This function should be called in the +initialize method of the receiver.
* </p>
* <p>If you add several behaviors to a class, be aware that the order of
* the additions is significant.
* </p>
*/
void
GSObjCAddClassBehavior(Class receiver, Class behavior)
{
@ -853,6 +829,55 @@ GSObjCAddClassBehavior(Class receiver, Class behavior)
GSFlushMethodCacheForClass (receiver);
}
void
GSObjCAddClassOverride(Class receiver, Class override)
{
unsigned int count;
Method *methods;
if (YES == class_isMetaClass(receiver))
{
fprintf(stderr, "Trying to add override (%s) to meta class (%s)\n",
class_getName(override), class_getName(receiver));
abort();
}
if (YES == class_isMetaClass(override))
{
fprintf(stderr, "Trying to add meta class as override (%s) to (%s)\n",
class_getName(override), class_getName(receiver));
abort();
}
if (class_getInstanceSize(receiver) < class_getInstanceSize(override))
{
fprintf(stderr, "Trying to add override (%s) with instance "
"size larger than class (%s)\n",
class_getName(override), class_getName(receiver));
abort();
}
BDBGPrintf("Adding override to class %s\n", class_getName(receiver));
BDBGPrintf(" instance methods from %s\n", class_getName(override));
/* Add instance methods */
methods = class_copyMethodList(override, &count);
if (methods != NULL)
{
GSObjCAddMethods (receiver, methods, YES);
free(methods);
}
/* Add class methods */
BDBGPrintf("Adding class methods from %s\n",
class_getName(object_getClass(override)));
methods = class_copyMethodList(object_getClass(override), &count);
if (methods != NULL)
{
GSObjCAddMethods (object_getClass(receiver), methods, YES);
free(methods);
}
GSFlushMethodCacheForClass (receiver);
}