Nat! bio photo

Nat!

Senior Mull

Twitter Github Twitch

mulle_objc: inheriting methods from protocols

Continued from mulle-objc: object layout, retain counting, finalize


A protocol in mulle-objc “lives” only in the compiler. Whereas in the legacy runtimes, a protocol existed at runtime as it’s own object, in mulle-objc it is just a hash value, whose presence can be queried on the class. At runtime you don’t know, what methods are part of a protocol.

As before there is nothing that stops you from creating a class with the same name as a protocol. This is put to good use now.

Inheriting methods from protocols

A class decides at runtime, what to inherit with a ->instance bitfield, that is part of the struct _mulle_objc_class:

Feature Description
MULLE_OBJC_CLASS_DONT_INHERIT_SUPERCLASS for completeness sake, useless
MULLE_OBJC_CLASS_DONT_INHERIT_CATEGORIES be obnoxious and seal your class
MULLE_OBJC_CLASS_INHERIT_PROTOCOLS inherit methods from protocol class, but not it’s categories
MULLE_OBJC_CLASS_INHERIT_PROTOCOLS_CATEGORIES inherit methods from categories of protocol class

A class can set these bits during +load or +initialize. I am toying with the idea of making MULLE_OBJC_CLASS_INHERIT_PROTOCOLS the default.

Alternative idea: A class has a method +inheritsProtocol:category: or even +inheritsSelector:protocol:category: and this method is queries, whenever the method cache is filled.

A scheme to have protocols with ivars (sort of)

Create a struct that contains the instance variables, the protocol needs. Define a method in the protocol to get the address of this struct in the instance variable area of an instance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
struct protocol_foo_struct
{
	unsigned int  a;
	unsigned int  b;
};


@protocol Foo

- (void) getFooStructP:(struct protocol_foo_struct **) foo;

@optional
- (void) setA:(unsigned int) value;

@end


//
// default implementation for Classes adopting Foo
//
@interface Foo
@end


@implementation Foo

- (void) setA:(unsigned int) value
{
	struct protocol_foo_struct *p;

	[self getFooStructP:&p];
	p->a = value;
}
@end




//  a class adopting Foo protocol
//
@interface Bar < Foo>
{
	long                         whatever;
   struct protocol_foo_struct   foo;
}


@implementation Bar

+ (void) load
{
   _mulle_objc_class_set_inheritance( self, MULLE_OBJC_CLASS_INHERIT_PROTOCOLS);
}


- (void) getFooStructP:(struct protocol_foo_struct **) foo
{
   *foo = &self->foo;
}

@end

Together with the extremely fast forwarding that mulle-objc offers through the meta-ABI, this makes multiple-inheritance-like schemes possible and performance wise acceptable.

I might get accused of “ripping off” Swift here, which apparently has something like this now. But when I designed this feature into the runtime some months ago, I didn’t know about it.


Continue to mulle-objc: present and absent language features


Post a comment

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

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