私は基本的にenum
が何であるか、そしてそれをいつ使うべきか理解していないと思います。
例えば:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
ここで本当に宣言されているものは何ですか?
ここでは3つのことが宣言されています。匿名の列挙型が宣言され、ShapeType
がその匿名の列挙のtypedefとして宣言され、3つの名前kCircle
、kRectangle
、およびkOblateSpheroid
が整数定数として宣言されます。
それを分解しましょう。最も単純な場合、列挙は次のように宣言できます。
enum tagname { ... };
これはタグtagname
で列挙を宣言します。 CおよびObjective-C(ただしnot C++)では、このmustへの参照の前に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
キーワードでenum tagname
を使用する必要がない場合は、enum
を匿名にしてtypedef名でのみ宣言できます。
typedef enum { ... } tagname;
さて、このケースでは、ShapeType
を匿名の列挙の型定義された名前として宣言しています。 ShapeType
は実際には単なる整数型であり、宣言にリストされている値の1つ(つまり、kCircle
、kRectangle
、およびkOblateSpheroid
)を保持する変数を宣言するためにのみ使用してください。ただし、キャストによってShapeType
変数に別の値を代入することができます。そのため、enum値を読み取るときは注意が必要です。
最後に、kCircle
、kRectangle
、およびkOblateSpheroid
は、グローバル名前空間で整数定数として宣言されています。特定の値が指定されていないため、それらは0から始まる連続した整数に割り当てられます。したがって、kCircle
は0、kRectangle
は1、そしてkOblateSpheroid
は2です。
Xcode 4.4以降、Appleはこのような列挙型を定義することをお勧めします。
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"ビデオを見ることができます ここ .
更新:公式文書へのリンク ここ 。
Enumは一連の順序付けられた値を宣言します - typedefはこれに便利な名前を追加するだけです。 1番目の要素は0などです。
typedef enum {
Monday=1,
...
} WORKDAYS;
WORKDAYS today = Monday;
上記は単にshapeTypeタグの列挙です。
可能な値のkCircle
、kRectangle
、またはkOblateSpheroid
を持つユーザー定義型。ただし、列挙型の内側の値(kCircleなど)は、列挙型の外側に表示されます。それを覚えておくことは重要です(例えば、int i = kCircle;
は有効です)。
64ビット変更のための更新: /による アップルのドキュメント / 64ビット変更について
列挙型も入力される:LLVMコンパイラでは、列挙型は列挙型のサイズを定義できます。これは、いくつかの列挙型も予想よりも大きいサイズを持つ可能性があることを意味します。他のすべての場合と同様に、解決策はデータ型のサイズについて想定しないことです。代わりに、適切なデータ型を使用して列挙値を変数に代入してください。
したがって、64ビットをサポートする場合は、 以下の構文のように 型でenumを作成する必要があります。
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-programmingのアップデート:
Swiftでは、構文が変更されました。
enum ControlButtonID: NSUInteger {
case kCircle , kRectangle, kOblateSpheroid
}
Enum(列挙の省略形)は、一連の値(列挙子)を列挙するために使用されます。値は、シンボル(Word)で表される抽象的なものです。たとえば、基本的な列挙型は次のようになります。
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
名前を付けるためのシンボルがないため、この列挙型は匿名と呼ばれます。しかし、それはまだ完全に正しいです。このように使うだけ
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
OK。人生は美しく、すべてが順調です。しかし、いつかmyGrandFatherPantSizeを格納するための新しい変数を定義するためにこのenumを再利用する必要があります、そしてあなたはこう書いています:
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
しかし、それからあなたはコンパイラエラー "enderatorの再定義"があります。実際のところ、問題は、最初にenumを列挙し、次に同じものを記述していることをコンパイラが確信できないことです。
その後、同じ場所の列挙子(ここではxs ... xxxxl)を複数の場所で再利用したい場合は、一意の名前でタグ付けする必要があります。 2回目にこのセットを使用するときは、タグを使用するだけです。しかし、このタグがWordの列挙型の代わりに列挙子のセットを置き換えることを忘れないでください。それから通常通りenumを使うように気をつけてください。このような:
// 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という接頭辞が付いたNiceマクロをいくつか発見しましょう。それはあなたが簡単に良い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;
enumは、structで実行できないenum要素に値を割り当てるために使用されます。そのため、完全な変数にアクセスする代わりに、列挙型の変数に割り当てる値によってアクセスできます。デフォルトでは0の代入で始まりますが、任意の値を代入することができ、enumの次の変数には前の値+1の値が代入されます。
Typedefを使うと、プログラマはあるObjective-Cの型を別の型として定義できます。例えば、
typedef intカウンタ。 Counter型をint型と等価になるように定義します。これにより、コードの可読性が大幅に向上します。
TypedefはCおよびC++のキーワードです。 (char、int、float、double、struct&enum) - 基本データ型の新しい名前を作成するために使用されます。
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
ここでは列挙型データ型を作成します ShapeType &enum型の新しい名前を書くことができます ShapeType 下記のように/
ShapeType shape1;
ShapeType shape2;
ShapeType shape3;
あなたは以下のフォーマットで、0から始まる生のデフォルト値を使うことができます。
あなたはあなた自身の特定の開始値を割り当てることができます。
typedef enum : NSUInteger {
kCircle, // for your value; kCircle = 5, ...
kRectangle,
kOblateSpheroid
} ShapeType;
ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
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;