Apa yang dimaksud dengan typedef enum di Objective-C?

1087

Saya tidak berpikir saya pada dasarnya mengerti apa itu enum itu, dan kapan menggunakannya.

Sebagai contoh:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Apa yang sebenarnya dinyatakan di sini?

Craig
sumber
2
Apakah jenis yang ditetapkan pengguna disebut "enum"? Itulah yang saya pikirkan, sampai saya menemukan kode yang memiliki beberapa deklarasi typedef enum.
Craig
8
Tidak, tipe yang ditentukan pengguna adalah ShapeType. Baca di typedef: en.wikipedia.org/wiki/Typedef
rampion
6
Typedef di Objective-C persis sama dengan typedef di C. Dan enum di Objective-C persis sama dengan enum di C. Ini menyatakan enum dengan tiga konstanta kCircle = 0, kRectangle = 1 dan kOblateSpheroid = 2, dan berikan enum ketik nama ShapeType. Jika Anda tidak tahu apa arti "typedef" dan "enum", beli buku tentang C.
gnasher729

Jawaban:

1565

Tiga hal yang sedang dinyatakan di sini: tipe enumerasi anonim dinyatakan, ShapeTypesedang mendeklarasikan typedef untuk itu pencacahan anonim, dan tiga nama kCircle, kRectangledankOblateSpheroid sedang dinyatakan sebagai konstanta integral.

Mari kita hancurkan itu. Dalam kasus yang paling sederhana, enumerasi dapat dinyatakan sebagai

enum tagname { ... };

Ini menyatakan enumerasi dengan tag tagname. Dalam C dan Objective-C (tetapi bukan C ++), referensi apa pun harus didahului dengan enumkata kunci. Sebagai contoh:

enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++

Untuk menghindari keharusan menggunakan enumkata kunci di mana-mana, typedef dapat dibuat:

enum tagname { ... };
typedef enum tagname tagname;  // declare 'tagname' as a typedef for 'enum tagname'

Ini dapat disederhanakan menjadi satu baris:

typedef enum tagname { ... } tagname;  // declare both 'enum tagname' and 'tagname'

Dan akhirnya, jika kita tidak perlu dapat menggunakan enum tagnamedengan enumkata kunci, kita dapat membuat enumanonim dan hanya menyatakan itu dengan nama typedef:

typedef enum { ... } tagname;

Sekarang, dalam hal ini, kami mendeklarasikan ShapeTypesebagai nama enumerasi anonim yang diketikkan. ShapeTypeadalah benar-benar hanya tipe integral, dan seharusnya hanya digunakan untuk mendeklarasikan variabel yang memegang salah satu dari nilai yang tercantum dalam deklarasi (yaitu, salah satu dari kCircle, kRectangle, dan kOblateSpheroid). Anda dapat menetapkan ShapeTypevariabel nilai lain dengan casting, jadi Anda harus berhati-hati saat membaca nilai enum.

Akhirnya, kCircle, kRectangle, dan kOblateSpheroiddinyatakan sebagai konstanta integral dalam namespace global. Karena tidak ada nilai spesifik yang ditentukan, mereka ditugaskan ke integer berturut-turut dimulai dengan 0, jadi kCircle0, kRectangle1, dan kOblateSpheroid2.

Adam Rosenfield
sumber
6
Penjelasan yang bagus - hanya untuk menambahkan satu hal, struct's mengikuti aturan penamaan yang serupa di C (tidak yakin tentang Objective-C).
Michael Burr
109
Objective-C adalah superset dari C. Semua aturan penamaan C struct di C sama validnya di Objective-C.
Sigigice
Luar biasa. Bisakah saya menggunakan enum C ++ style dan juga tidak perlu menulis enum :)
user4951
11
Anda dapat menggunakan enums gaya C ++ jika file yang Anda deklarasikan adalah file .mm daripada .m. Objective-C ++ sangat kuat bukan kepalang.
Kevin Hoffman
14
Dan begitu Anda menemukan jawaban ini, ada baiknya melihat NS_ENUM dan NS_OPTIONS yang baru. Tutorial di sini: nshipster.com/ns_enum-ns_options dan SO di sini: stackoverflow.com/questions/14080750/…
Snowcrash
254

Apple merekomendasikan mendefinisikan enum seperti ini sejak Xcode 4.4 :

typedef enum ShapeType : NSUInteger {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Mereka juga menyediakan makro yang berguna NS_ENUM:

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

Definisi ini memberikan pengecekan tipe yang lebih kuat dan penyelesaian kode yang lebih baik. Saya tidak dapat menemukan dokumentasi resmi NS_ENUM, tetapi Anda dapat menonton video "Modern Objective-C" dari sesi WWDC 2012 di sini .


PEMBARUAN
Tautan ke dokumentasi resmi di sini .

Vladimir Grigorov
sumber
13
Bagian tentang "Peningkatan Enum" dimulai pada 5:58
vikingosegundo
5
Seperti mengomentari jawaban lain, lihat penjelasan NS_ENUMmakro Apple oleh NSHipster: NSHipster.com/ns_enum-ns_options
Basil Bourque
1
Ini adalah tautan ke dokumentasi resmi tentang NS_ENUM: developer.apple.com/library/ios/releasenotes/ObjectiveC/…
YoGiN
50

Enum mendeklarasikan seperangkat nilai yang dipesan - typedef hanya menambahkan nama yang berguna untuk ini. Elemen 1 adalah 0 dll.

typedef enum {
Monday=1,
...
} WORKDAYS;

WORKDAYS today = Monday;

Di atas hanyalah penghitungan tag shapeType.

hburde
sumber
34

Sebuah didefinisikan tipe user yang memiliki nilai yang mungkin dari kCircle, kRectangle, atau kOblateSpheroid. Nilai-nilai di dalam enum (kCircle, dll) terlihat di luar enum. Penting untuk mengingat hal itu ( int i = kCircle;valid, misalnya).

Brian Mitchell
sumber
30

Pembaruan untuk Perubahan 64-bit: Menurut apple docs tentang perubahan 64-bit,

Pencacahan Juga Diketik: Dalam kompiler LLVM, jenis yang disebutkan dapat menentukan ukuran pencacahan. Ini berarti bahwa beberapa tipe yang disebutkan mungkin juga memiliki ukuran yang lebih besar dari yang Anda harapkan. Solusinya, seperti dalam semua kasus lainnya, adalah tidak membuat asumsi tentang ukuran tipe data. Sebagai gantinya, tetapkan nilai enumerasi apa pun ke variabel dengan tipe data yang tepat

Jadi, Anda harus membuat enum dengan tipe seperti sintaks di bawah ini jika Anda mendukung 64-bit.

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

atau

typedef enum ShapeType : NSUInteger {
   kCircle,
   kRectangle,
   kOblateSpheroid
} ShapeType;

Jika tidak, itu akan menyebabkan peringatan sebagai Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Pembaruan untuk pemrograman cepat:

Di cepat, ada perubahan sintaksis.

enum ControlButtonID: NSUInteger {
        case kCircle , kRectangle, kOblateSpheroid
    }
Mani
sumber
Jika perlu meneruskan mendeklarasikan enum (NS_ENUM): stackoverflow.com/a/42009056/342794
lal
25

Enum (singkatan enumeration) digunakan untuk menghitung satu set nilai (enumerator). Nilai adalah hal abstrak yang diwakili oleh simbol (kata). Misalnya, enum dasar bisa jadi

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };

Enum ini disebut anonim karena Anda tidak memiliki simbol untuk menamainya. Tetapi itu masih sangat benar. Gunakan saja seperti ini

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;

Baik. Hidup itu indah dan semuanya berjalan dengan baik. Tetapi suatu hari Anda perlu menggunakan kembali enum ini untuk mendefinisikan variabel baru untuk menyimpan myGrandFatherPantSize, lalu Anda menulis:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;

Tetapi kemudian Anda memiliki kesalahan kompiler "redefinition of enumerator". Sebenarnya, masalahnya adalah bahwa kompiler tidak yakin bahwa Anda pertama kali enum dan Anda yang kedua menjelaskan hal yang sama.

Kemudian jika Anda ingin menggunakan kembali enumerator yang sama (di sini xs ... xxxxl) di beberapa tempat Anda harus menandainya dengan nama yang unik. Kali kedua Anda menggunakan set ini, Anda hanya perlu menggunakan tag. Tapi jangan lupa bahwa tag ini tidak menggantikan kata enum tetapi hanya kumpulan enumerator. Kemudian berhati-hatilah menggunakan enum seperti biasa. Seperti ini:

// 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;

Anda dapat menggunakannya dalam definisi parameter juga:

// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;

Anda bisa mengatakan bahwa menulis ulang enum di mana-mana tidak nyaman dan membuat kode terlihat agak aneh. Kamu benar. Tipe nyata akan lebih baik.

Ini adalah langkah terakhir dari kemajuan besar kita menuju puncak. Dengan hanya menambahkan typedef, mari kita ubah enum kita menjadi tipe nyata. Oh, hal terakhir, typedef tidak diperbolehkan di dalam kelas Anda. Kemudian tentukan jenis Anda tepat di atas. Lakukan seperti ini:

// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type

@interface myClass {
   ...
   size_type myGrandMotherDressSize, myGrandFatherPantSize;
   ...
}

Ingat bahwa tag ini opsional. Maka sejak di sini, dalam hal ini, kami tidak menandai enumerator tetapi hanya untuk menentukan tipe baru. Maka kita tidak benar-benar membutuhkannya lagi.

// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;

@interface myClass : NSObject {
  ...
  size_type myGrandMotherDressSize, myGrandFatherPantSize;
  ...
}
@end

Jika Anda mengembangkan di Objective-C dengan XCode saya membiarkan Anda menemukan beberapa makro bagus diawali dengan NS_ENUM. Itu akan membantu Anda untuk mendefinisikan enum yang baik dengan mudah dan terlebih lagi akan membantu penganalisa statis untuk melakukan beberapa pemeriksaan menarik untuk Anda sebelum dikompilasi.

Enum yang bagus!

Vincent Zgueb
sumber
Saya selalu berpikir "mengapa ada orang yang menjawab pertanyaan yang sudah dijawab dan diterima". Wah, aku salah sepanjang waktu! Ini adalah jawaban terbaik dan membantu pemula seperti saya!
rak appdev
10

typedefberguna untuk mendefinisikan kembali nama tipe variabel yang ada. Ini menyediakan cara singkat & bermakna untuk memanggil tipe data. misalnya:

typedef unsigned long int TWOWORDS;

di sini, tipe unsigned long int didefinisikan ulang dari tipe TWOWORDS. Dengan demikian, kita sekarang dapat mendeklarasikan variabel tipe unsigned long int dengan menulis,

TWOWORDS var1, var2;

dari pada

unsigned long int var1, var2;
Rajneesh071
sumber
7
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

maka Anda dapat menggunakannya seperti: -

 ShapeType shape;

dan

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

sekarang kamu bisa menggunakannya seperti: -

enum ShapeType shape;
Vivek Sehalagi
sumber
3

enum digunakan untuk memberikan nilai pada elemen enum yang tidak dapat dilakukan dalam struct. Jadi setiap kali alih-alih mengakses variabel lengkap kita bisa melakukannya dengan nilai yang kita tetapkan untuk variabel dalam enum. Secara default dimulai dengan penugasan 0 tetapi kita dapat menetapkan nilai apa pun dan variabel berikutnya dalam enum akan diberi nilai nilai sebelumnya +1.

Priyanka Naik
sumber
3

Anda dapat menggunakan dalam format di bawah ini, nilai baku baku mulai dari 0, jadi

  • kCircle adalah 0,
  • kRectangle adalah 1,
  • kOblateSpheroid adalah 2.

Anda dapat menetapkan nilai awal spesifik Anda sendiri.

typedef enum : NSUInteger {
    kCircle, // for your value; kCircle = 5, ...
    kRectangle,
    kOblateSpheroid
} ShapeType;

ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
Bilal Arslan
sumber
2

Typedef memungkinkan pemrogram untuk mendefinisikan satu tipe Objective-C sebagai yang lain. Sebagai contoh,

typedef int Counter; mendefinisikan tipe Counter agar setara dengan tipe int. Ini secara drastis meningkatkan keterbacaan kode.


sumber
2

Typedef adalah Kata Kunci dalam C dan C ++. Ini digunakan untuk membuat nama baru untuk tipe data dasar (char, int, float, double, struct & enum) .

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Di sini ia membuat enumerasi tipe data ShapeType & kita dapat menulis nama baru untuk enum tipe ShapeType seperti yang diberikan di bawah ini

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;
Yogeesh HT
sumber
1

enum dapat mengurangi banyak jenis "kesalahan" dan membuat kode lebih mudah dikelola

#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER

Definisi tersebut tidak memiliki kendala. Itu hanyalah sebuah penggantian. Itu tidak dapat membatasi semua kondisi negara. Ketika NEGARA ditugaskan ke 5, program akan salah, karena tidak ada negara yang cocok. Tetapi kompiler tidak akan memperingatkan STATE = 5

Jadi lebih baik menggunakan seperti ini

typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;
Marcus Thornton
sumber