私はそれが何であるか、enum
いつそれを使うべきかを根本的に理解しているとは思いません。
例えば:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
ここで実際に何が宣言されていますか?
私はそれが何であるか、enum
いつそれを使うべきかを根本的に理解しているとは思いません。
例えば:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
ここで実際に何が宣言されていますか?
回答:
三つのことがここで宣言されています:匿名の列挙型が宣言され、ShapeType
その匿名の列挙のtypedefを宣言し、3人の名前されている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'
これは1行に簡略化できます。
typedef enum tagname { ... } tagname; // declare both 'enum tagname' and 'tagname'
私たちが使用できるようにする必要がない場合そして最後に、enum tagname
とenum
キーワード、我々は作ることができenum
、匿名をし、唯一のtypedef名でそれを宣言します。
typedef enum { ... } tagname;
さて、このケースでShapeType
は、匿名の列挙のtypedefされた名前であることを宣言しています。 ShapeType
実際には整数型であり、そして唯一の(である、のいずれかの宣言に列挙された値のいずれかを保持する変数を宣言するために使用されるべきであるkCircle
、kRectangle
などをkOblateSpheroid
)。ShapeType
ただし、キャストによって変数に別の値を割り当てることができるため、列挙値を読み取るときは注意する必要があります。
最後に、kCircle
、kRectangle
、およびkOblateSpheroid
グローバル名前空間での積分定数として宣言されています。具体的な値が指定されていなかったので、彼らは、0から始まる連続した整数に割り当てられますので、kCircle
0であり、kRectangle
1、kOblateSpheroid
2です。
Xcode 4.4以降では、このような列挙型を定義することをお勧めします。
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
また、便利なマクロも提供しますNS_ENUM
。
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
これらの定義により、型チェックが強化され、コード補完が改善されます。の公式ドキュメントは見つかりませんでしたがNS_ENUM
、WWDC 2012セッションの「Modern Objective-C」ビデオはこちらでご覧いただけます。
UPDATE
公式ドキュメントへのリンクはこちら。
NS_ENUM
、NSHipsterによるAppleのマクロの説明を参照してください:NSHipster.com/ns_enum-ns_options
の可能な値を持つユーザー定義型kCircle
、kRectangle
またはkOblateSpheroid
。ただし、列挙型の内部の値(kCircleなど)は列挙型の外側に表示されます。それを覚えておくことが重要int i = kCircle;
です(たとえば、有効です)。
64ビットの変更に対する更新: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
迅速なプログラミングのための更新:
迅速に、構文の変更があります。
enum ControlButtonID: NSUInteger {
case kCircle , kRectangle, kOblateSpheroid
}
enum(列挙の省略形)は、一連の値(列挙子)を列挙するために使用されます。値は、記号(単語)で表される抽象的なものです。たとえば、基本的な列挙型は
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
この列挙型は、名前を付けるシンボルがないため、匿名と呼ばれます。しかし、それはまだ完全に正しいです。このように使うだけ
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
OK。人生は美しく、すべてがうまくいきます。しかし、ある日、この列挙型を再利用して、myGrandFatherPantSizeを格納する新しい変数を定義する必要がある場合は、次のように記述します。
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
しかし、「列挙子の再定義」というコンパイラエラーが発生します。実際、問題は、コンパイラが最初に列挙型であり、2番目に同じものを記述していることを確信していないことです。
次に、同じセットの列挙子(ここではxs ... xxxxl)を複数の場所で再利用する場合は、一意の名前でタグ付けする必要があります。このセットを2回目に使用するときは、タグを使用する必要があります。ただし、このタグは列挙型の単語を置き換えるのではなく、列挙子のセットを置き換えるだけであることを忘れないでください。次に、いつものように列挙型を使用するように注意してください。このような:
// 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;
enumをどこでも書き直すのは便利ではなく、コードが少し奇妙に見えると言うことができます。あなたが正しいです。実際のタイプの方が良いでしょう。
これは、サミットへの大きな前進の最後のステップです。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
XCodeを使用してObjective-Cで開発している場合は、NS_ENUMで始まるいくつかの素晴らしいマクロを発見できます。これは、適切な列挙型を簡単に定義するのに役立ち、さらに、静的アナライザーがコンパイルする前に興味深いチェックを行うのに役立ちます。
良い列挙!
typedef
既存の変数タイプの名前を再定義するのに役立ちます。これは、データ型を呼び出すための短くて意味のある方法を提供します。例えば:
typedef unsigned long int TWOWORDS;
ここでは、unsigned long int型がTWOWORDS型に再定義されています。したがって、次のように記述することで、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;
以下のフォーマットで使用できます。0から始まるRawデフォルト値なので、
独自の開始値を割り当てることができます。
typedef enum : NSUInteger {
kCircle, // for your value; kCircle = 5, ...
kRectangle,
kOblateSpheroid
} ShapeType;
ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
typedefを使用すると、プログラマはObjective-Cの型を別の型として定義できます。例えば、
typedef int Counter; Counterタイプをintタイプと同等に定義します。これにより、コードの可読性が大幅に向上します。
enumは多くのタイプの「エラー」を減らし、コードをより管理しやすくします
#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER
定義に制約はありません。それは単に代替品です。状態のすべての条件を制限することはできません。STATEが5に割り当てられている場合、一致する状態がないため、プログラムは正しくありません。しかし、コンパイラーはSTATE = 5に警告しません
だからこのように使う方がいい
typedef enum SampleState {
SampleStateGood = 0,
SampleStateBad,
SampleStateOther
} SampleState;
SampleState state = SampleStateGood;