#import <Foundation/Foundation.h>

@interface Base : NSObject
{
    id<NSObject> obj;
    void *ptr;
}
- (instancetype)initWithObject: (id<NSObject>)anObj pointer: (void *)aPtr;
- (void)run;
- (void)method: (id<NSObject>)anObj with: (void *)aPtr;
@end

@implementation Base

- (instancetype)initWithObject: (id<NSObject>)anObj pointer: (void *)aPtr
{
    if ((self = [super init]) != nil)
    {
	obj = [anObj retain];
	ptr = aPtr;
    }
    return self;
}

- (void)dealloc
{
    [obj release];
    [super dealloc];
}

- (void)run
{
    [self method: obj with: ptr];
}

- (void)method: (id<NSObject>)anObj with: (void *)aPtr
{
    NSLog(@"In base implementation of -method:with:");
}

@end

@interface A : Base
@end

@implementation A

- (void)method: (id<NSObject>)anObj with: (void *)aPtr
{
    NSLog(@"method: %@ with: %p", anObj, aPtr);
}

@end

@interface B : Base
@end

@implementation B

- (instancetype)initWithObject: (id<NSObject>)anObj pointer: (void *)aPtr
{
    [self release];
    return nil;
}

- (instancetype)initWithClass: (Class)aClass pointer: (void *)aPtr
{
    return [super initWithObject: aClass pointer: aPtr];
}

- (void)method: (Class)aClass with: (void *)aPtr
{
    NSLog(@"method: %@ with: %p", aClass, aPtr);
}

@end

@interface C : Base
@end

@implementation C

- (instancetype)initWithObject: (id<NSObject>)anObj pointer: (void *)aPtr
{
    [self release];
    return nil;
}

- (instancetype)initWithObject: (NSObject *)anObj and: (NSObject *)anotherObj
{
    return [super initWithObject: anObj pointer: anotherObj];
}

- (void)method: (NSObject *)anObj with: (NSObject *)anotherObj
{
    NSLog(@"method: %@ with: %p", anObj, anotherObj);
}

@end

int
main()
{
    @autoreleasepool
    {
	NSObject *o = [NSNull null];
	A *a = [[A alloc] initWithObject: o pointer: &o];
	B *b = [[B alloc] initWithClass: [o class] pointer: &o];
	C *c = [[C alloc] initWithObject: o and: o];

#define nsstr(s) @#s
#define run(v) do { NSLog(@"Calling [" nsstr(v) @" run] for %@", v); [v run]; } while (0)
	run(a);
	run(b);
	run(c);
    }
}
