14 ответов:
здесь объявляются три вещи: аноним перечисленный тип объявляется,
ShapeTypeобъявляется typedef для этого анонимного перечисления, и три имениkCircle,kRectangleиkOblateSpheroidобъявляются как интегральные константы.давайте разберем это. В простейшем случае перечисление может быть объявлено как
enum tagname { ... };это объявляет перечисление с тегом
tagname. В C и Objective-C (но не C++), любой ссылки на это должны будет начинаться сenumключевое слово. Например:enum tagname x; // declare x of type 'enum tagname' tagname x; // ERROR in C/Objective-C, OK in C++чтобы избежать необходимости использовать
enumключевое слово везде, typedef может быть создан:enum tagname { ... }; typedef enum tagname tagname; // declare 'tagname' as a typedef for 'enum tagname'это можно упростить в одну строку:
typedef enum tagname { ... } tagname; // declare both 'enum tagname' and 'tagname'и, наконец, если мы не должны быть в состоянии использовать
enum tagnameСenumключевое слово, мы можем сделатьenumанонимно и только объявить его с помощью typedef имя:typedef enum { ... } tagname;Итак, в этом случае, мы объявляем
ShapeTypeдля определение типа объед имя анонимное перечисление.ShapeTypeна самом деле является просто целочисленным типом и должен использоваться только для объявления переменных, которые содержат одно из значений, перечисленных в объявлении (то есть одно изkCircle,kRectangleиkOblateSpheroid). Вы можете назначитьShapeTypeпеременной другое значение с помощью литья, поэтому вы должны быть осторожны при чтении значений enum.наконец,
kCircle,kRectangle, иkOblateSpheroidобъявляются как интегральные константы в глобальном пространстве имен. Поскольку конкретные значения не были указаны, они присваиваются последовательным целым числам, начинающимся с 0, поэтомуkCircle0, тоkRectangle1 иkOblateSpheroidв 2.
Apple рекомендует определять перечисления, подобные этому, начиная с Xcode 4.4:
typedef enum ShapeType : NSUInteger { kCircle, kRectangle, kOblateSpheroid } ShapeType;Они также предоставляют удобный макрос NS_ENUM:
typedef NS_ENUM(NSUInteger, ShapeType) { kCircle, kRectangle, kOblateSpheroid };эти определения обеспечивают более сильную проверку типа и лучшее завершение кода. Я не смог найти официальную документацию NS_ENUM, но вы можете посмотреть видео "Modern Objective-C" с сессии WWDC 2012 здесь.
обновление: ссылка на официальную документацию здесь.
перечисление объявляет набор упорядоченных значений - typedef просто добавляет удобное имя к этому. 1-й элемент равен 0 и т. д.
typedef enum { Monday=1, ... } WORKDAYS; WORKDAYS today = Monday;выше просто перечисление тегов shapeType.
определенный пользователем тип, возможные значения
kCircle,kRectangleилиkOblateSpheroid. Однако значения внутри перечисления (kCircle и т. д.) видны за пределами перечисления. Важно иметь это в виду (int i = kCircle;- это справедливо, например).
обновление для 64-битного изменения: Согласно apple docs о 64-битных изменениях,
перечисления также Типизируются : в компиляторе LLVM перечисляемые типы могут определите размер перечисления. Это означает, что некоторые из перечисленных типы также могут иметь размер больше, чем вы ожидаете. Этот решение, как и во всех других случаях, - сделать никаких предположений о размер типа данных. Вместо этого присвойте переменной все перечисленные значения с правильным типом данных
так надо создать перечисление с типом как показано ниже синтаксис, если вы поддерживаете 64-разрядную версию.
typedef NS_ENUM(NSUInteger, ShapeType) { kCircle, kRectangle, kOblateSpheroid };или
typedef enum ShapeType : NSUInteger { kCircle, kRectangle, kOblateSpheroid } ShapeType;в противном случае, это приведет к предупреждения как
Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeTypeобновление для swift-программирования:
в swift есть изменение синтаксиса.
enum ControlButtonID: NSUInteger { case kCircle , kRectangle, kOblateSpheroid }
Enum-это определенный пользователем тип данных. ПЕРЕЧИСЛИМЫЕ ТИПЫ ДАННЫХ Перечисленные переменные типа данных могут принимать только те значения, которые были объявлены ранее.
enum month { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec }; enum month this_month; this_month = feb;в приведенном выше объявлении месяц объявляется как перечисленный тип данных. Он состоит из набора значений с января по декабрь. Численно Ян получает значение 1, февраль-значение 2 и так далее.
переменная this_month объявляется того же типа, что и месяц, затем присваивается значение, связанное с февраль. This_month не может быть присвоено никаких значений, кроме указанных в списке инициализации для объявления месяца.
перечисление (аббревиатура перечисления) используется для перечисления набора значений (счетчиками). Значение-это любая абстрактная вещь, представленная символом (словом). Например, базовое перечисление может быть
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };это перечисление называется анонимным, потому что у вас нет символа, чтобы назвать его. Но это все равно совершенно правильно. Просто используйте его так
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;ОК. Жизнь прекрасна и все идет хорошо. Но однажды вам нужно повторно использовать это перечисление, чтобы определить новый переменная для хранения myGrandFatherPantSize, то вы пишете:
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize; enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;но тогда у вас есть ошибка компилятора "переопределение перечислителя". На самом деле проблема заключается в том, что компилятор не уверен, что вы первый перечисление и ваш второй описать то же самое.
затем, если вы хотите повторно использовать тот же набор перечислителей (здесь xs...xxxxl) в нескольких местах вы должны пометить его уникальным именем. Во второй раз, когда вы используете этот набор, вам просто нужно использовать тег. Но не забывайте, что это тег не заменяет слово перечисления, а только набор перечислителей. Затем позаботьтесь о том, чтобы использовать перечисление, как обычно. Вот так:
// Here the first use of my enum enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize; // here the second use of my enum. It works now ! enum sizes myGrandFatherPantSize;вы также можете использовать его в определении параметров:
// Observe that here, I still use the enum - (void) buyANewDressToMyGrandMother:(enum sizes)theSize;можно сказать, что переписывание перечисления везде не удобно и делает код выглядит немного странно. Вы правы. Настоящий тип был бы лучше.
это последний шаг нашего великого продвижения к вершине. Просто добавив typedef давайте преобразуем наше перечисление в реальном типе. О, последнее, typedef не допускается в вашем классе. Затем определите свой тип чуть выше. Сделайте это так:
// enum definition enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl }; typedef enum sizes size_type @interface myClass { ... size_type myGrandMotherDressSize, myGrandFatherPantSize; ... }помните, что тег является необязательным. Затем, поскольку здесь в этом случае мы не помечаем перечислители, а просто определяем новый тип. Тогда нам больше не нужна.
// enum definition typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type; @interface myClass : NSObject { ... size_type myGrandMotherDressSize, myGrandFatherPantSize; ... } @endесли вы разрабатываете в ObjectiveC с XCode я позволю вам обнаружить некоторые хорошие макросы с префиксом NS_ENUM. Это должно помочь вам определить хорошие перечисления легко и более того поможет статическому анализатору сделать несколько интересных проверок для вас перед компиляцией.
Хороший Перечисление !
typedefполезно для переопределения имени существующего типа переменной. Это обеспечивает короткий и значимый способ вызова типа данных. например:typedef unsigned long int TWOWORDS;здесь тип беззнаковый long int-это переопределить, чтобы быть из двух слов, типа. Таким образом, теперь мы можем объявить переменные типа unsigned long int, написав,
TWOWORDS var1, var2;вместо
unsigned long int var1, var2;
typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType;затем вы можете использовать его как :-
ShapeType shape;и
вы можете использовать его как:-enum { kCircle, kRectangle, kOblateSpheroid } ShapeType;enum ShapeType shape;
enum используется для присвоения значения элементам enum, которые не могут быть выполнены в struct. Поэтому каждый раз вместо доступа к полной переменной мы можем сделать это по значению, которое мы присваиваем переменным в enum. По умолчанию он начинается с присвоения 0, но мы можем присвоить ему любое значение, и следующей переменной в enum будет присвоено значение Предыдущее значение +1.
typedef позволяет программисту определить один тип Objective-C как другой. Например,
typedef Int Counter; определяет тип счетчика, эквивалентный типу int. Это значительно улучшает читаемость кода.
Typedef является ключевым словом в C и c++. Он используется для создания новых имен для основных типов данных (символ, целое число, с плавающей точкой, двойной, структура & перечисление).
typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType;здесь он создает перечислимый тип данных ShapeType & мы можем написать новые имена для перечислимого типа ShapeType как указано ниже
ShapeType shape1; ShapeType shape2; ShapeType shape3;
вы можете использовать в приведенном ниже формате, необработанное значение по умолчанию, начиная с 0, так что
- kCircle равно 0,
- kRectangle - это 1,
- kOblateSpheroid является 2.
вы можете назначить свое собственное конкретное начальное значение.
typedef enum : NSUInteger { kCircle, // for your value; kCircle = 5, ... kRectangle, kOblateSpheroid } ShapeType; ShapeType circleShape = kCircle; NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
перечисление может уменьшить многие типы "ошибок" и сделать код более управляемым
#define STATE_GOOD 0 #define STATE_BAD 1 #define STATE_OTHER 2 int STATE = STATE_OTHERопределение не имеет ограничений. Это просто подмена. Она не способна ограничивать все условия государства. Когда состояние присваивается 5, программа будет неправильной, потому что нет соответствующего состояния. Но компилятор не собирается предупреждать STATE = 5
Так что лучше использовать вот так
typedef enum SampleState { SampleStateGood = 0, SampleStateBad, SampleStateOther } SampleState; SampleState state = SampleStateGood;
Comments