代码之家  ›  专栏  ›  技术社区  ›  George

不匹配-init方法名

  •  4
  • George  · 技术社区  · 14 年前

    例如,我创建了两个类ClassA&ClassB,它们都有一个名为-initWithSomething的init方法: 一个使用(NSDate*)作为“something”,另一个使用(NSString*)

    // 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
    

    #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”的行不会产生警告。

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

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

    3 回复  |  直到 14 年前
        1
  •  3
  •   Richard J. Ross III    14 年前

    我想问题是 +alloc id .

    这意味着可以对它调用任何方法,编译器将看到导入的第一个具有签名的方法 -initWithSomething 是为了上课 A ,它需要类型为 NSDate * .

    而且,我相信 +stringWithFormat 返回 身份证件 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
  •  2
  •   shreyasva    14 年前

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

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

        3
  •  1
  •   Logan Capaldo    14 年前

    +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* ).