为什么我需要自我塑造身份? [英] Why do I need to cast self to id?

查看:156
本文介绍了为什么我需要自我塑造身份?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个接受(id)参数的init方法:

I have an init method that takes an (id) argument:


    -(id) initWithObject:(id) obj;

我试图这样调用:


    [[MyClass alloc] initWithObject:self];

但是XCode抱怨这个参数是一个不同的Objective-C类型类型不匹配或间接性错误级别)。

But XCode is complaining about the argument being a "distinct Objective-C type" (which usually indicates a type mismatch or level of indirection error).

如果我显式地将自己转换为(id)警告消失。在任一情况下,代码按预期运行。
有趣的是,在下一行,我将自我传递给另一个也需要id的方法,并且工作正常。

If I explicitly cast self to (id) the warning goes away. In either case the code runs as expected. Interestingly, on the next line I'm passing self to another method that also takes an id, and that works fine.

我想知道如果我或者是编译器的特殊性?

I'm wondering if I'm missing something subtle - or is it a peculiarity of the compiler?

我不完全舒服,直到我确定为什么它是必要的原因

I'm not entirely comfortable just casting it until I'm sure of the reasons why it's necessary.

我被要求提供更多代码。不确定还有很多其他相关的。这是我的实际代码,使调用。注意,它本身在init方法中。这是调用 initWithSource 的警告:

I've been asked to supply more code. Not sure there's much else that's relevant. Here's my actual code that makes the call. Note that it is, itself, within an init method. It's the call to initWithSource that's giving the warning:


-(id) initWithFrame:(CGRect) frame
{
    self = [super initWithFrame: frame];
    if( self )
    {
        delegate = nil;
        touchDelegate = [[TBCTouchDelegate alloc] initWithSource:self];
        [touchDelegate.viewWasTappedEvent addTarget: self action:@selector(viewWasTapped:)];
    }
    return self;
}

这里是调用的init方法:

And here's the init method being called:


-(id) initWithSource:(id) sourceObject
{
    self = [super init];
    if (self != nil) 
    {
        // Uninteresting initialisation snipped
    }
    return self;
}


推荐答案

code> initWithSource:在具有冲突参数类型的不同类上的方法名称。记住,如果变量被键入 id ,编译器不知道它是什么类。因此,如果在 id -typed对象上调用 initWithSource:,并且多个类都有 initWithSource :方法,编译器本质上只是选择其中的一个。如果它选择了错误的,那么你会得到一个明确的Objective-C类型错误。

Typically this means there's multiple initWithSource: method names on different classes with conflicting argument types. Remember, if a variable is typed as id the compiler does not know what class it is. Thus if you call initWithSource: on an id-typed object and multiple classes have an initWithSource: method, the compiler essentially just picks one of the two. If it picks the "wrong" one, well, you get a "distinct Objective-C type" error.

那么为什么会发生这种情况呢?我不是100%肯定,但记住, + [TBCTouchDelegate alloc] 返回 id 。因此,链接alloc / init调用相当于:

So why is this happening to you? I'm not 100% sure, but remember that +[TBCTouchDelegate alloc] returns an id. Thus chaining the alloc/init calls is equivalent to this:

id o = [TBCTouchDelegate alloc];
touchDelegate = [o initWithSource:self];

因此,你正在调用 initWithSource: id -typed变量。如果有一个冲突的 initWithSource:方法,你可能会得到这个编译错误。

Hence, you are calling initWithSource: on an id-typed variable. If there's a conflicting initWithSource: method, you could get this compiler error.

有冲突的方法吗?我检查了系统,唯一的冲突是在 NSAppleScript

Is there a conflicting method? I checked the system, and the only conflicting one was in NSAppleScript:

- (id)initWithSource:(NSString *)source;

现在 NSAppleScript em>基金会的一部分,但我注意到这是iPhone代码。所以也许你只是在编译模拟器而不是设备时才得到这个错误?

Now NSAppleScript is part of Foundation, but I noticed this is iPhone code. So perhaps you only get this error when compiling for the simulator, and not the device?

在任何情况下,如果这是你的问题,你可以通过拆分alloc / init到两个不同的行:

In any case, if this is your problem, you could get around it by splitting alloc/init onto two different lines:

touchDelegate = [TBCTouchDelegate alloc];
touchDelegate = [touchDelegate initWithSource:self];

现在,您正在调用 initWithSource:对一个完全类型的变量(而不是 id -typed),因此编译器不再需要猜测选择哪一个。或者你可以从 + alloc 投入回报:

Now, you're calling initWithSource: on a fully-typed variable (instead of id-typed), so the compiler no longer has to guess which one to pick. Or you could cast the return from +alloc:

touchDelegate = [(TBCTouchDelegate *)[TBCTouchDelegate alloc] initWithSource:self];

另一个解决方案是重命名 initWithSource:避免冲突,并可能使其更具描述性。你不会说什么类当前命名也不是源是什么,所以我不能抛出任何可能性。

Another solution is to rename initWithSource: to avoid the conflict and perhaps make it more descriptive. You don't say what the class is currently named nor what the "source" is for, so I cannot throw out any possibilities.

这篇关于为什么我需要自我塑造身份?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆