为什么有些变量在 Objective-C 中用 * 星号声明
Why Some Variables are Declared with an * Asterisk in Objective-C
我才刚刚开始学习Objective-C。我很困惑地看到某些类型的变量有时用 * 星号声明,而另一些则没有。例如,这些是用 *
:
声明的
@property NSString *firstName;
NSString * mainString = @"Hello World!";
NSNumber *longNumber = @42l;
NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
而这些不是:
int someInteger = 42;
NSInteger anInteger = 64;
id firstObject = @"someString";
NSRange substringRange = [mainString rangeOfString:@"long"];
我从 Apple 的文档中找到了这个解释:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Both these properties are for Objective-C objects, so they use an asterisk to indicate that they are C pointers.
但是这个解释过于笼统和模糊,我无法理解这个概念。我知道 type *
表示它是一个指针类型,这个类型存储那个类型的指针。但为什么有些类型用 *
声明,有些则没有?
int
类型不是对象。它是一种 C 语言的“原始数据类型”。您通常直接与原始 C 数据类型交互。例如,
int i = 0; // it’s now `0`
i = 42; // it’s now `42`
NSInteger
只是另一种原始数据类型 long
的别名。 NSRange
是一个结构(因此,也不是一个对象),所以同样的规则适用。因此,对于与这些原始数据类型的基本交互,通常不需要 *
指针引用。 (实际上有时您还会处理指向原始数据类型的指针,但这超出了本问题的范围。)
但是NSString
、NSNumber
、NSArray
,但是,是对象,所以声明时必须使用指针。
请注意,您已将 id
包含在未使用 *
的后一个列表中:
id firstObject = @"foo";
要非常小心。这实际上有点误导,因为 firstObject
实际上 是 指向 @"someString"
的指针,一个 NSString
对象。 id
是我们通常使用 *
声明指针的方式的一个例外,并在 Objective-C is a Dynamic Language) 中进行了讨论,“id
类型定义了一个通用对象指针。”
这类似于声明一个 NSString
指针,但是“你丢失了有关该对象的编译时信息”。将指向 NSString *
的 id
指针与以下语法进行比较:
NSString *secondObject = @"bar";
后面的secondObject
是NSString *
指针,但是因为我们明确声明它是一个NSString *
指针,所以编译器知道你正在处理一个字符串(因此编译器可以对该指针的后续使用执行更大的验证)。使用 id
,您不享受此编译时验证。
例如,这里有两次对两个 NSString
对象调用 removeObject
方法的无效尝试。 NSString
没有这样的方法。 NSString *
参考提供了有用的编译时错误消息,id
没有提供给我们:
现在,如果您使用 id
类型并尝试 运行 该代码,它会在尝试调用 firstObject
上的 removeObject
时崩溃。但是,在可能的情况下,让编译器在编译时告诉我们错误要好得多,而不是在 运行-time.
所以应该谨慎使用 id
模式,只有当你真的需要 Objective-C 的动态类型行为时才使用。
我才刚刚开始学习Objective-C。我很困惑地看到某些类型的变量有时用 * 星号声明,而另一些则没有。例如,这些是用 *
:
@property NSString *firstName;
NSString * mainString = @"Hello World!";
NSNumber *longNumber = @42l;
NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
而这些不是:
int someInteger = 42;
NSInteger anInteger = 64;
id firstObject = @"someString";
NSRange substringRange = [mainString rangeOfString:@"long"];
我从 Apple 的文档中找到了这个解释:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Both these properties are for Objective-C objects, so they use an asterisk to indicate that they are C pointers.
但是这个解释过于笼统和模糊,我无法理解这个概念。我知道 type *
表示它是一个指针类型,这个类型存储那个类型的指针。但为什么有些类型用 *
声明,有些则没有?
int
类型不是对象。它是一种 C 语言的“原始数据类型”。您通常直接与原始 C 数据类型交互。例如,
int i = 0; // it’s now `0`
i = 42; // it’s now `42`
NSInteger
只是另一种原始数据类型 long
的别名。 NSRange
是一个结构(因此,也不是一个对象),所以同样的规则适用。因此,对于与这些原始数据类型的基本交互,通常不需要 *
指针引用。 (实际上有时您还会处理指向原始数据类型的指针,但这超出了本问题的范围。)
但是NSString
、NSNumber
、NSArray
,但是,是对象,所以声明时必须使用指针。
请注意,您已将 id
包含在未使用 *
的后一个列表中:
id firstObject = @"foo";
要非常小心。这实际上有点误导,因为 firstObject
实际上 是 指向 @"someString"
的指针,一个 NSString
对象。 id
是我们通常使用 *
声明指针的方式的一个例外,并在 Objective-C is a Dynamic Language) 中进行了讨论,“id
类型定义了一个通用对象指针。”
这类似于声明一个 NSString
指针,但是“你丢失了有关该对象的编译时信息”。将指向 NSString *
的 id
指针与以下语法进行比较:
NSString *secondObject = @"bar";
后面的secondObject
是NSString *
指针,但是因为我们明确声明它是一个NSString *
指针,所以编译器知道你正在处理一个字符串(因此编译器可以对该指针的后续使用执行更大的验证)。使用 id
,您不享受此编译时验证。
例如,这里有两次对两个 NSString
对象调用 removeObject
方法的无效尝试。 NSString
没有这样的方法。 NSString *
参考提供了有用的编译时错误消息,id
没有提供给我们:
现在,如果您使用 id
类型并尝试 运行 该代码,它会在尝试调用 firstObject
上的 removeObject
时崩溃。但是,在可能的情况下,让编译器在编译时告诉我们错误要好得多,而不是在 运行-time.
所以应该谨慎使用 id
模式,只有当你真的需要 Objective-C 的动态类型行为时才使用。