为什么[NSMutableString stringWithString:@“”]有效?

时间:2011-12-01 15:55:32

标签: objective-c nsstring nsmutablestring

只是想知道:

NSString中有一个名为+stringWithString:的静态方法。 这不会在NSMutableString中重新声明/覆盖,因此我们无法假设这将返回NSMutableString。事实上即使在NSString类中,返回类型也定义为iddoc states

  

返回值
  通过复制aString

中的字符创建的字符串

在我的知识中,我缺少什么目标C来理解为什么这会起作用并返回NSMutableString?特别是因为基类NSString不知道我们想要一个可变字符串作为回报。

可以说内部[Class alloc]会被调用,它会生成NSMutableString类型的对象,但即使这是纯粹的猜测,因为我们没有源代码而且stringWithString:可以做无论内心想要什么。

是否所有这些类方法都在子类中重新实现?如果是,为什么不记录这个?

4 个答案:

答案 0 :(得分:6)

  

在NSString中有一个名为+ stringWithString的静态方法:

更合适的是,这是一种课堂方法。

  

这不会在NSMutableString

中重新声明/重写

在cocoa中,子类不需要重新声明该方法。事实上,它只会产生很多噪音(IMO)。它只需要重新定义方法来提供自定义实现。

  

所以我们不能假设这会返回一个NSMutableString。

我们必须假设它将返回一个可变字符串。子类可以根据需要重新定义其初始化器和便捷构造器,以便在不公开重新声明方法的情况下满足所需的合同 - 它只需要在基础实现不足时定义方法。

  

在我的知识中,我缺少什么目标C来理解为什么这会起作用并返回一个NSMutableString?特别是因为基类NSString不知道我们想要一个可变的字符串作为回报。

它'知道'因为你写了[NSMutableString stringWithString:@"bah"]而不是[NSString stringWithString:@"bah"]。与实例方法类似,类方法具有隐式self,允许它们通过类方法传递类型。因此,可以根据需要重新定义/重写类方法。类方法也可以使用self来确定或消息它们的类型(例子很快)。

  

可以说内部[类alloc]被调用,它将生成NSMutableString类型的对象,但即使这是纯粹的猜测,因为我们没有源代码和stringWithString:可以在内部做任何想做的事。

不应该猜测。在这种情况下,如果您返回 immutable 字符串,则应该提交错误。否则,无论是否使用了一个或多个定义,它都会像宣传的那样工作。

  

是否所有这些类方法都在子类中重新实现?

对于便捷构造函数,通过其中一个指定的初始值设定项更为常见:

这样的实现可以采取以下形式:

@implementation NSString
+ (id)stringWithString:(NSString *)arg
{
    // self is either +NSString or +NSMutableString
    return [[[self alloc] initWithString:arg] autorelease];
}

虽然通常可以做出例外情况,但优化的不可变/可变类型通常也是如此:

@implementation NSString
+ (id)stringWithString:(NSString *)arg
{
  return [arg imp_isMutable] ? [[[self alloc] initWithString:arg] autorelease] : arg;
}
...
@implementation NSMutableString
+ (id)stringWithString:(NSString *)arg
{
  return [[[self alloc] initWithString:arg] autorelease];
}
...
  

如果是,为什么不记录这个?

当唯一的区别是你要求的类类型时,它们不应该被重新声明或重新编写,除非它们与基类或特殊注释有一些偏差 - 即使在这种情况下,最好创建一个方法用另一个名字。

答案 1 :(得分:3)

NSMutableStringNSString的子类,因此任何调用NSMutableString的方法都可以正常工作,并在有意义时返回NSMutableString。我想到的唯一不会遵循的方法是copy,它按惯例返回一个不可变的实例。

这就是为什么你的初始化方法返回id而不是具体实例,以及为什么所有类方法都应该使用[self alloc]而不是[MYActualClass alloc]

答案 2 :(得分:3)

您可以像这样编写初始化程序:

+ (id) stringWithString: (NSString*) foo
{
    return [[self alloc] initWithString:foo];
}

现在,当您在NSString上调用此初始值设定项时,[self alloc]会返回NSString并返回NSString的实例。但是当您调用[NSMutableString stringWithString:@"…"]时,[self alloc]消息的结果为NSMutableString,因此初始值设定项会返回一个可变字符串。

答案 3 :(得分:3)

(Justin说,但澄清)

  

在NSString中有一个名为+ stringWithString的静态方法:这个   在NSMutableString中没有重新声明/重写,所以我们不能假设   这将返回一个NSMutableString。实际上甚至在NSString中   class返回类型定义为id ...

首先, Objective-C没有静态方法。 Objective-C有类方法。类方法的行为与实例方法完全相同(其中类是元类的实例),并且可以继承,覆盖等...

因此,正如NSMutableString继承characterAtIndex:并且可以覆盖它以执行特殊操作,如果需要,NSMutableString可以对类方法执行相同的操作。

另请注意,类不需要在头中声明它从超类中重写的方法。框架中的类通常显式地声明重写方法,因为重写的方法应该与父类完全相同,但是被覆盖以在子类的需求的上下文中工作。