0

在 Objective-C 中的朋友类上发现了这个 StackOverflow 问题,这与我试图解决的问题相似,但并不完全相同。所以我想扩展他们的例子。

假设我想要给猴子多个香蕉的能力,他会保留一系列他自己的香蕉。当我告诉他吃饭时,他从他的阵列中吃东西。然后我可以让他随机给我一个香蕉:

香蕉.h

@interface Banana : NSObject
- (BOOL)isPeeled;
@end

香蕉.m

#import "Banana.h"

@implementation Banana
{
    @private
    BOOL peeled;
}

- (id)init
{
    self = [super init];
    if (self)
    {
        peeled = NO;
    }
    return self;
}

- (void)peel // PRIVATE METHOD
{
    peeled = YES;
}

- (BOOL)isPeeled
{
    return peeled;
}
@end

猴子.h

#import "Banana.h"

@interface Monkey : NSObject
- (void)give:(Banana *)aBanana;
- (void)eat;
- (Banana *)getBanana;
@end

猴子.m

#import "Monkey.h"

@implementation Monkey
{
    @private
    NSMutableArray *bananas;
}

- (id)init
{
    self = [super init];
    if (self)
    {
        bananas = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)give:(Banana *)aBanana
{
    [bananas addObject:aBanana];
}

- (void)eat
{
    BOOL hungry = YES;
    for (int i = 0; i < bananas.count; i++)
    {
        if (!banana.isPeeled)
        {
            hungry = NO;
            [banana peel];
            break;
        }
    }
    if (hungry)
    {
        NSLog(@"Monkey ANGRY!");
    }
}

- (Banana *)getBanana
{
    int r = arc4random_uniform(bananas.count);
    return [bananas objectAtIndex:r];
}
@end

在这种情况下,Banana.h并且Monkey.h将是我正在分发的库中的公共标题。我的库的预期用途如下所示:

客户端应用程序.m

#import "MonkeyLib/MonkeyLib.h"

@implementation SomeClass

- (void)someMethod
{
    Banana *oneBanana = [[Banana alloc] init];
    Monkey *oneMonkey = [[Monkey alloc] init];
    [oneMonkey give:oneBanana];
    [oneMonkey eat];
    Banana *twoBanana = [oneMonkey getBanana];
    if (twoBanana.isPeeled)
    {
        NSLog(@"No sad monkeys!");
    }
}

@end

上面代码的直接问题是我的库无法编译,因为该类的接口没有Banana定义peel方法(由 使用Monkey.m

我在这个问题开头链接的 StackOverflow 问题建议创建第三个头文件:

BananaPrivate.h

@interface Banana (PrivateMethods)
- (void)peel;
@end

然后在Monkey.m我可以导入BananaPrivate.h并且我可以突然调用该peel方法。但是这失败了,因为当我尝试导入时,我创建了一个冲突——我在导入时BananaPrivate.h已经定义了BananaBanana.hMonkey.h

我无法从中删除Banana.hMonkey.h因为其中一种方法Monkey返回类型的实例Banana

我通过这样的子分类找到了一个古怪的解决方法Banana

内部香蕉.h

@interface InternalBanana : Banana
- (void)peel;
@end

然后Monkey.m我就可以安然无恙#import "InternalBanana.h"。然而这有两个问题:

  1. 它仅适用于我的 Monkey实例化的 Bananas (如果我的库的用户实例化一个 Banana 并将其传递给我的 Monkey,它将是一个 Banana 而不是 InternalBanana)
  2. 我必须创建一个InternalBanana.m文件,但在这个文件中我无法定义peel. 尝试在其中定义peelInternalBanana.m引发peeled未定义的错误,因为peeled它是超类的私有变量。如果我在其中定义peel并且InternalBanana.m它只调用[super peel],那也将失败,因为Banana没有定义peel方法。虽然这可行,但它确实会导致 Xcode 抛出一个警告,指出没有方法定义peel(但尽管有警告,它仍会构建并运行)

这个猴子生意的正确解决方案是什么?

4

0 回答 0