在 Objective C 中声明枚举的不同方式
Different ways of declaring enum in Objective C
为什么在 objective c 中有这么多不同的方法来声明枚举?这很令人困惑。
下面这些有区别还是都一样?
enum WeekDays{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef enum : NSUInteger {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
} WeekDays;
typedef NS_ENUM(NSInteger, WeekDays){
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
enum {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef NSInteger WeekDays;
Is there any difference between the following or are they all the same?
存在一些差异,一些是由于 C - 它是 Objective-C 的基础 - 如果您正在考虑将 Objective-C 代码导入 Swift。
你的第一个例子:
enum WeekDays { Monday, ..., Friday };
是一个原始的Cenum
。这声明了一个 type enum WeekDays
,其中 底层类型 为 int
,以及 5 个 literal 值。
现在 C 不是强类型语言:这里的字面量值不是 enum WeekDays
类型而是 int
类型;并且 enum WeekDays
类型的变量可以被赋值为 Monday
到 Friday
以外的值,并且可以被赋值给 int
变量而无需强制转换或转换。第一个字面值(此处为 Monday
)将具有 int
值 0
,随后的值将比前面的字面量大一个值(因此此处 Friday
具有值 4
)。示例:
enum WeekDays one;
int two;
one = Monday;
two = Tuesday; // assigning enum literal to int is OK
two *= 42; // will produce an int value outside of Monday thru Friday
one = two; // which can be assigned to an enum WeekDays
one = 34; // int values can also be directly assigned
所有 enum
变体在这种方式下很弱。然而,许多编译器,包括 Xcode 自至少 v8 以来使用的编译器,在某些情况下会发出警告(而不是错误),例如如果 switch
表达式是 enum
类型并且 case
标签省略了一些声明的文字或具有声明值之外的值。
给文字明确的值
可以为 enum
文字指定特定值,而不是依赖默认值。例如给 Monday
值 1
到 Friday
具有值 5
:
enum WeekDays { Monday = 1, ..., Friday };
像往常一样,没有明确值的文字比前面的文字多分配一个。这些值也不需要连续:
enum WeekDays { Monday = 1, Tuesday = 42, Wednesday = 3, Thursday, Friday };
使用 typedef
许多 C 类型声明复杂且难以解析(它们是填充离子测验问题),C typedef
允许特定类型的 别名 被宣布。 typedef
通常与 enum
声明一起使用,以避免在使用类型时必须使用 enum
。例如:
typedef enum WeekDays { Monday, ..., Friday } WeekDays;
声明别名 WeekDays
表示 enum WeekDays
。例如:
WeekDays one; // means exactly the same as the previous
// declaration for one
enum WeekDays one; // also valid and means the same thing
在上面的声明中看到两次 WeekDays
可能会造成混淆,或者对某些人来说只是打字太多,可以省略:
typedef enum { Monday, ..., Friday } WeekDays;
这与之前的声明略有不同,WeekDays
现在是 anonymous enum
的别名。对于这样的类型,第一种声明形式现在无效:
enum Weekdays one; // invalid, no such enum
WeekDays one; // valid
更改基础类型
默认情况下 enum
的基础类型是 int
。可以指定不同的 integral 类型,该类型必须足够大以容纳文字表示的所有值。整数类型是整数、无符号整数和字符类型。通过在enum
标签后添加: <type>
来指定底层类型,字面量可以赋予相同类型的特定值。例如:
typedef enum Vowels : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
如上所述,可以使用匿名枚举:
typedef enum : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
使用NS_ENUM
NS_ENUM
是一个 (Apple) Objective-C 便利宏,它扩展为 typedef
和 enum
声明。例如:
typedef NS_ENUM(NSInteger, WeekDays) { Monday, ..., Friday };
扩展为:
typedef enum WeekDays : NSInteger WeekDays;
enum WeekDays : NSInteger { Monday, ..., Friday };
避免前向声明等同于:
typedef enum WeekDays : NSInteger { Monday, ..., Friday } WeekDays;
使用Xcodev8,至少,使用NS_ENUM
和上面直接typedef
.
在编译器检查和警告上没有区别
当NS_ENUM
有所作为时
如果你写的 Objective-C 将被 Swift 使用,那么使用 NS_ENUM
确实会有所不同:使用 NS_ENUM
声明的枚举将作为Swift enum
;而直接声明的一个将作为 Swift struct
和全局 read-only 计算属性的集合导入,每个文字一个。
当前的 Apple 文档(Using Swift with Cocoa and Objective-C (Swift 4.0.3 ),可通过 iBooks)
获取
最后,回到你的例子
以上应该能让你找出不同之处:
默认Cenum
,底层类型为int
,类型用作enum WeekDays
别名 C enum
,基础类型为 NSUinteger
,类型用作 WeekDays
NS_ENUM
生成 enum
,底层类型为 NSInteger
,类型可以称为 WeekDays
或 enum WeekDays
这声明了两个 不同的类型并且可能会产生警告。第一个是没有别名的匿名 enum
,所以以后不能用这种类型引入变量。它引入的文字是 int
类型的。第二个是 NSInteger
的别名。在 64 位系统上,NSInteger
是 64 位,而 int
是 32 位,所以字面量类型 (int
) 和 "enum" 类型 (WeekDays
) 可能会产生警告。与前三个版本一样,将不会检查进一步的 switch
语句因为它们只是基于 NSInteger
。这个版本看起来像是模仿 NS_ENUM
的错误尝试,不应该使用(它本身是无效的,只是没有按照它的建议去做)。
希望所有的启发多于混淆!
为什么在 objective c 中有这么多不同的方法来声明枚举?这很令人困惑。
下面这些有区别还是都一样?
enum WeekDays{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef enum : NSUInteger {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
} WeekDays;
typedef NS_ENUM(NSInteger, WeekDays){
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
enum {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef NSInteger WeekDays;
Is there any difference between the following or are they all the same?
存在一些差异,一些是由于 C - 它是 Objective-C 的基础 - 如果您正在考虑将 Objective-C 代码导入 Swift。
你的第一个例子:
enum WeekDays { Monday, ..., Friday };
是一个原始的Cenum
。这声明了一个 type enum WeekDays
,其中 底层类型 为 int
,以及 5 个 literal 值。
现在 C 不是强类型语言:这里的字面量值不是 enum WeekDays
类型而是 int
类型;并且 enum WeekDays
类型的变量可以被赋值为 Monday
到 Friday
以外的值,并且可以被赋值给 int
变量而无需强制转换或转换。第一个字面值(此处为 Monday
)将具有 int
值 0
,随后的值将比前面的字面量大一个值(因此此处 Friday
具有值 4
)。示例:
enum WeekDays one;
int two;
one = Monday;
two = Tuesday; // assigning enum literal to int is OK
two *= 42; // will produce an int value outside of Monday thru Friday
one = two; // which can be assigned to an enum WeekDays
one = 34; // int values can also be directly assigned
所有 enum
变体在这种方式下很弱。然而,许多编译器,包括 Xcode 自至少 v8 以来使用的编译器,在某些情况下会发出警告(而不是错误),例如如果 switch
表达式是 enum
类型并且 case
标签省略了一些声明的文字或具有声明值之外的值。
给文字明确的值
可以为 enum
文字指定特定值,而不是依赖默认值。例如给 Monday
值 1
到 Friday
具有值 5
:
enum WeekDays { Monday = 1, ..., Friday };
像往常一样,没有明确值的文字比前面的文字多分配一个。这些值也不需要连续:
enum WeekDays { Monday = 1, Tuesday = 42, Wednesday = 3, Thursday, Friday };
使用 typedef
许多 C 类型声明复杂且难以解析(它们是填充离子测验问题),C typedef
允许特定类型的 别名 被宣布。 typedef
通常与 enum
声明一起使用,以避免在使用类型时必须使用 enum
。例如:
typedef enum WeekDays { Monday, ..., Friday } WeekDays;
声明别名 WeekDays
表示 enum WeekDays
。例如:
WeekDays one; // means exactly the same as the previous
// declaration for one
enum WeekDays one; // also valid and means the same thing
在上面的声明中看到两次 WeekDays
可能会造成混淆,或者对某些人来说只是打字太多,可以省略:
typedef enum { Monday, ..., Friday } WeekDays;
这与之前的声明略有不同,WeekDays
现在是 anonymous enum
的别名。对于这样的类型,第一种声明形式现在无效:
enum Weekdays one; // invalid, no such enum
WeekDays one; // valid
更改基础类型
默认情况下 enum
的基础类型是 int
。可以指定不同的 integral 类型,该类型必须足够大以容纳文字表示的所有值。整数类型是整数、无符号整数和字符类型。通过在enum
标签后添加: <type>
来指定底层类型,字面量可以赋予相同类型的特定值。例如:
typedef enum Vowels : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
如上所述,可以使用匿名枚举:
typedef enum : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
使用NS_ENUM
NS_ENUM
是一个 (Apple) Objective-C 便利宏,它扩展为 typedef
和 enum
声明。例如:
typedef NS_ENUM(NSInteger, WeekDays) { Monday, ..., Friday };
扩展为:
typedef enum WeekDays : NSInteger WeekDays;
enum WeekDays : NSInteger { Monday, ..., Friday };
避免前向声明等同于:
typedef enum WeekDays : NSInteger { Monday, ..., Friday } WeekDays;
使用Xcodev8,至少,使用NS_ENUM
和上面直接typedef
.
当NS_ENUM
有所作为时
如果你写的 Objective-C 将被 Swift 使用,那么使用 NS_ENUM
确实会有所不同:使用 NS_ENUM
声明的枚举将作为Swift enum
;而直接声明的一个将作为 Swift struct
和全局 read-only 计算属性的集合导入,每个文字一个。
当前的 Apple 文档(Using Swift with Cocoa and Objective-C (Swift 4.0.3 ),可通过 iBooks)
获取最后,回到你的例子
以上应该能让你找出不同之处:
默认C
enum
,底层类型为int
,类型用作enum WeekDays
别名 C
enum
,基础类型为NSUinteger
,类型用作WeekDays
NS_ENUM
生成enum
,底层类型为NSInteger
,类型可以称为WeekDays
或enum WeekDays
这声明了两个 不同的类型并且可能会产生警告。第一个是没有别名的匿名
enum
,所以以后不能用这种类型引入变量。它引入的文字是int
类型的。第二个是NSInteger
的别名。在 64 位系统上,NSInteger
是 64 位,而int
是 32 位,所以字面量类型 (int
) 和 "enum" 类型 (WeekDays
) 可能会产生警告。与前三个版本一样,将不会检查进一步的switch
语句因为它们只是基于NSInteger
。这个版本看起来像是模仿NS_ENUM
的错误尝试,不应该使用(它本身是无效的,只是没有按照它的建议去做)。
希望所有的启发多于混淆!