Struct Embedding in Objective-C

Objective-C supports composition of types through various mechanisms, including categories and protocols. While it doesn’t have a direct equivalent to Go’s struct embedding, we can achieve similar functionality using these features.

#import <Foundation/Foundation.h>

@interface Base : NSObject

@property (nonatomic, assign) NSInteger num;

- (NSString *)describe;

@end

@implementation Base

- (NSString *)describe {
    return [NSString stringWithFormat:@"base with num=%ld", (long)self.num];
}

@end

@interface Container : NSObject

@property (nonatomic, strong) Base *base;
@property (nonatomic, copy) NSString *str;

@end

@implementation Container

@end

@protocol Describer <NSObject>

- (NSString *)describe;

@end

@interface Container (Describer) <Describer>
@end

@implementation Container (Describer)

- (NSString *)describe {
    return [self.base describe];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // When creating objects, we need to initialize the composition explicitly
        Container *co = [[Container alloc] init];
        co.base = [[Base alloc] init];
        co.base.num = 1;
        co.str = @"some name";
        
        // We can access the base's properties through the container
        NSLog(@"co={num: %ld, str: %@}", (long)co.base.num, co.str);
        
        // We can also access the base's properties directly
        NSLog(@"also num: %ld", (long)co.base.num);
        
        // We can call the describe method on the container
        NSLog(@"describe: %@", [co describe]);
        
        // We can use the container as a Describer
        id<Describer> d = co;
        NSLog(@"describer: %@", [d describe]);
    }
    return 0;
}

In this Objective-C version:

  1. We define a Base class with a num property and a describe method.

  2. We define a Container class that has a Base object as a property, along with a str property.

  3. We define a Describer protocol that declares the describe method.

  4. We use a category to make Container conform to the Describer protocol, implementing the describe method by forwarding to the base object.

  5. In the main function, we create a Container object, set its properties, and demonstrate accessing the composed Base object’s properties and methods.

  6. We also show how the Container object can be used as a Describer.

To run this program, save it as StructEmbedding.m and compile it with:

$ clang -framework Foundation StructEmbedding.m -o StructEmbedding
$ ./StructEmbedding
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1

This example demonstrates how Objective-C can achieve similar functionality to Go’s struct embedding using composition, categories, and protocols. While the syntax is different, the concepts of type composition and interface implementation are present in both languages.