【问题标题】:Why objects like NSString and NSNumber cannot be overwritten?为什么像 NSString 和 NSNumber 这样的对象不能被覆盖?
【发布时间】:2013-06-24 10:52:18
【问题描述】:

关于同一主题的帖子很多,这可能是一个愚蠢的问题,但我一直无法理解这个概念。

我知道将可变字符串分配给不可变字符串时会出现的问题,以及为什么我应该使用复制来避免这些问题。

我不太明白的是:不能修改 NSString 到底是什么意思?

如果我这样做:

NSString *foo = @"Hello World!";
foo = @"Hello everybody!";

我知道我不是在修改 foo 的值,而是用新实例替换旧实例。但是,如何定义我不能重写可变对象?

更新 我尝试运行以下代码:

-(void)immutable
{
    NSString *myString1 = @"Hello!";
    NSString *myString2 = myString1;

    NSLog(@"myString1 address: %p", &myString1); //Prints 0xbfffdb30
    NSLog(@"myString2 address: %p", &myString2); //Prints 0xbfffdb2c

    myString2 = @"Good bye!";
    NSLog(@"myString2 address: %p", &myString2); //Prints 0xbfffdb2c

    NSMutableString *myMutableString = [NSMutableString stringWithString:@"Hello"];
    NSString *myString3 = myMutableString;

    NSLog(@"myMutableString address: %p", &myMutableString); //Prints 0xbfffdb28
    NSLog(@"myString3 address: %p", &myString3); //Prints 0xbfffdb24

    [myMutableString setString:@"Hello World"];
    NSLog(@"myString3: %@", myString3); //Prints Hello World

    myString3 = myString1;
    NSLog(@"myString3 address: %p", &myString3); //Prints 0xbfffdb24

    [myMutableString setString:@"Nothing to do"];
    NSLog(@"myString3: %@", myString3); //Prints Hello!
}

myString1 和 myString2 的地址不同我并不感到惊讶,因为它们都是不可变对象。但即使在为 myString2 分配了不同的字符串之后,它仍然指向与以前相同的地址。不应该改吗?

但是在 myMutableString 和 myString3 的情况下,即使 myMutableString 的任何更改都会反映在 myString3 中,它们仍然有不同的地址。 在我将 myString1 分配给 myString3 之后,myString3 指向的地址没有改变,但是它不再与 myMutableString 相关,因为我对其所做的每一个更改都将不再反映在 myString3 中。 是什么导致 myString3 和 myMutableString 首先被链接?

【问题讨论】:

  • &myString 获取本地指针的地址,而不是对象的地址。在方法开始处设置断点,并在调试窗格中观察对象的地址。
  • 谢谢!我对测试的结果感到很困惑,但现在一切都清楚了。

标签: objective-c nsstring immutability mutable


【解决方案1】:

当您编写 foo = @"Hello World!"; 时,foo 指向一个具有数据 "Hello World!"NSString 对象,假设该对象位于地址 10。

当你写foo = @"Hello everybody!"时,foo现在指向一个新的对象,它有数据"Hello everybody!",假设这个对象位于地址50。第一个对象根本没有被修改,你只是做了foo 指向另一个地址的另一个对象。

如果这些字符串是可变的,你可以修改内容,

NSMutableString *foo = @"Hello World!".mutableCopy; //LEt's say, it's @ adress 10
[foo appendString:@"How is it going?"]; // IT's still @ adress 10, but with new content.

foo 现在指向地址为 10 的对象,该对象已修改内容 "Hello World!How is it going?"

在第一种情况下,您无法修改NSString,因为它没有为您提供任何方法来更改该地址的数据。这就是不变性。另一方面,NSMutableString 通过appendString:appendString: 等方法为您提供了这种能力。这样您就可以在同一地址更改对象的内容,而无需创建新对象来进行这些更改。

【讨论】:

  • 很好的答案,我做了一些小的修改。作为一般评论,就使用而言,NSMutableString 并没有真正使用。通常我们会复制字符串或附加它。可变对象主要用于NSMutableArrayNSMutableDictionary(还有其他对象,但这是最常见的两个),因为您可能经常需要动态数组和字典。但如果你使用这些,记得有时传递一个copy,如果它们是你的公共 API 的一部分。如果您不希望任何人弄乱可变对象,请将它们设为不可变对象。反之亦然mutableCopy
  • 感谢您的回复。我用我尝试过的一些代码更新了这个问题,但在阅读了你的答案后,它并没有像我预期的那样工作。
  • @Lovato 您对可变数据容器的看法是正确的。如果您需要从头开始并通过许多步骤构建字符串,可变字符串可能会很有用。例如,通过检查是否应添加每个参数来添加参数来构建 URL。
猜你喜欢
  • 2015-09-09
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 2016-04-08
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
相关资源
最近更新 更多