【问题标题】:Mismatched -init method names-init 方法名称不匹配
【发布时间】:2011-05-03 01:45:31
【问题描述】:

我发现了一个奇怪的场景,它在 XCode 中产生了一个我认为不是有效警告的编译器警告。

作为示例,我创建了两个类,ClassA 和 ClassB,它们都有一个名为 -initWithSomething 的 init 方法: 一个将 (NSDate *) 作为“某物”,另一个将 (NSString *)

A 类

// ClassA.h
#import <Foundation/Foundation.h>

@interface ClassA : NSObject {
}
-(id)initWithSomething:(NSDate *)something;
@end

// ClassA.m
#import "ClassA.h"

@implementation ClassA
-(id)initWithSomething:(NSDate *)something {
    if (self = [super init]) {
    }
    return self;
}
@end

B 类

// ClassB.h
#import <Foundation/Foundation.h>

@interface ClassB : NSObject {
}
-(id)initWithSomething:(NSString *)something;
@end

// ClassB.m
#import "ClassB.h"

@implementation ClassB
-(id)initWithSomething:(NSString *)something {
    if (self = [super init]) {
    }
    return self;
}
@end

实现另一个同时使用 ClassA 和 ClassB 的类

#import "ExampleClass.h"
#import "ClassA.h"
#import "ClassB.h"

@implementation ExampleClass

-(void)doSomething {
    NSDate *date = [NSDate date];
    NSString *string = [NSString stringWithFormat:@"Test"];

    ClassA *classA = [[ClassA alloc] initWithSomething:date];
    ClassB *classB = [[ClassB alloc] initWithSomething:string]; // Produces "Incompatible pointer types sending 'NSString *' to parameter of type 'NSDate *'
    ClassB *classB2 = [[ClassB alloc] initWithSomething:[NSString stringWithFormat:@"Test"]]; // Does NOT produce a warning
    ClassB *classB3 = [[ClassB alloc] initWithSomething:@"Test"]; // Produces the same warning as above.

    [classA release];
    [classB release];
    [classB2 release];
    [classB3 release];
}

这是编译器错误吗?似乎这些行中的任何一行都不应该产生警告,特别是因为“classB2”被初始化的行没有产生警告。
这段代码实际上运行良好,正确的类'-initWithSomething: 被调用并传递了适当类型的参数。

显然,更明确的方法名称可以避免这个问题,但我想知道为什么编译器无法处理这个问题。

注意: 我应该补充一点,这似乎只发生在 -init 方法中,任何其他实例或类函数似乎都不会产生警告。

【问题讨论】:

  • 我不知道为什么有人会否决这个问题,这是个好问题

标签: objective-c xcode


【解决方案1】:

我认为问题在于+alloc 返回一个通用的id

这意味着可以在其上调用任何方法,并且编译器将看到导入的第一个具有签名-initWithSomething 的方法用于A 类,它需要NSDate * 类型的对象。

另外,我相信+stringWithFormat 方法返回的id 可以与NSDate 兼容。

编辑:

这个问题的简单解决方案:

@interface ClassA

+(ClassA *) typeSafeAlloc;

// ...
@end

@implementation ClassA

+(ClassA *) typeSafeAlloc
{
    // self is the class variable,  which is the same as:
    // return [ClassA alloc];
    return [self alloc];
}
@end

然后用 ClassB 重复这个过程(typeSafeAlloc 返回一个ClassB 对象)

【讨论】:

    【解决方案2】:

    alloc 返回一个 id 类型的对象,因此编译器假定 initWithSomething 属于 Class A(它遇到的第一个具有方法名称的类接口)。

    有点像 [(ClassB*)[ClassB alloc] initWithSomething:string]; 应该可以解决问题。

    【讨论】:

      【解决方案3】:

      +stringWithFormat的返回类型

      返回使用给定格式字符串作为模板创建的字符串,其余参数值将被替换到该模板中。

      + (id)stringWithFormat:(NSString *)format, ...

      (来自http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html

      编译器知道字符串是NSString*,与@"literals" 相同。但是,id 可以是任何东西(甚至是 NSSDate*)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-29
        • 2011-12-18
        • 2021-06-12
        • 2018-01-07
        • 2011-09-01
        • 1970-01-01
        • 2012-08-14
        相关资源
        最近更新 更多