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.