Nat! bio photo

Nat!

Senior Mull.

Twitter RSS

Github

mulle-objc, Objective C gains multiple inheritance

This is my activity report for August

Currently multiple inheritance functionality in ObjC is done via composition. You place another instance of an object into the object and forward messages to it. Because forwarding wasn't very fast before mulle-objc, this has rarely been done. It's also somewhat clumsy, because you have to figure out on a per-selector basis, what to forward and what not.

As you may or may not have noticed, in mulle-objc there is something called protocolclasses now. A protocolclass (see: mixin) looks like this:

@class Foo;
@protocol Foo;

Maybe I'll add a @protocolclass keyword sometime, if I have really nothing better to do.

Then for @interface Bar : NSObject < Foo>, the runtime will look for a root class Foo (existence required) and Bar will inherit its methods. Protocolclass methods override any superclass (NSObject in this case) methods.

So now you can compose objects via protocols:

@class ColorProperty;
@protocol ColorProperty
@property( retain) id  color;
- (id) HSVColor;
- (id) RGBColor;
@end

// @implementation ColorProperty not shown here

@interface ColoredObject : NSObject <  ColorProperty>
@end

@implementation ColoredObject
// i get it all for free
@end

But in terms of mulle-objc there is nothing new about this :) What is new, that I had to rethink and redo what super does. super usually searches in the superclass. But then it is not possible to override - easily - methods that you gain from protocolclasses.

But it turns out I needed that.

In the MulleObjC Foundation you create singletons, by simply adopting the protocol MulleObjCSingleton. The magic is done in the +initialize method of MulleObjCSingleton. But that method became obscured, when I had to write an +initialize in the adopting class:

@interface Foo : NSObject < MulleObjCSingleton>
@end

@implementation Foo

+ (void) initialize
{
   [super initialize];  // traditionally calls NSObject
}

So I changed super to start searching through the protocolclasses first. To make this possible I had to redo the super call mechanism. That code wasn't the fastest to begin with, but with some thought I was able to speed it up to very near regular method call speeds.

With the change of super's semantics, one can call what mulle-objc does multiple inheritance. Because protocolclasses must be root classes, this is a limited - but IMO sensibly limited - form of multiple inheritance, that doesn't suffer from common multiple inheritance scheme problems (as I understand it). And compared to composition, it's much easier (zero effort) to implement.

Here is the inheritance chain for a more complex example (search will go from A to E):

@class B; @protocol B;
@class C; @protocol C;
@class E; @protocol E;

@interface D < E > @end
@interface A : D < C, B> @end
@interface A( Y) @end
@interface A( X) @end

A category A( X) overrides A(Y). (Assume A( Y) is loaded before A( X)). A(Y) overrides A as categories do.

A inherits from D and adopts C and B. B and C override D. Protocolclasses are searched from back to front (like categories). So B overrides C.

Other changes

Different hash for method selectors

I invested some more time in the hash generation of selectors and changed my algorithm from fnv1 to fnv1a (with a different shift) factor. From my research this should give somewhat better dispersion for the most common cache sizes (and selector names).

Compiler outputs better MetaABI code for methods with no prototypes

Passing structs to methods with no prototypes didn't work. This has been fixed.

Stuff to do next

  • As clang 5.0.0 is near, this will be the base for the next community release. I will try to get the debugger and the compiler into one redistributable package, because currently getting the debugger to compile is a hassle.
  • Wouldn't it be nice if a category could call [overridden foo] to inherit from the overridden method ? The mulle-objc-runtime can do this already, but the compiler has no support.

Post a comment

All comments are held for moderation; basic HTML formatting accepted.

Name:
E-mail: (not published)
Website: