Variabel Level Kelas Statis-C Statis

143

Saya memiliki Film kelas, yang masing-masing menyimpan ID unik. Dalam C #, Java dll saya dapat mendefinisikan currentID int statis dan setiap kali saya mengatur ID saya dapat meningkatkan currentID dan perubahan terjadi pada tingkat kelas bukan tingkat objek. Bisakah ini dilakukan di Objective-C? Saya merasa sangat sulit untuk menemukan jawaban untuk ini.

Cur
sumber

Jawaban:

158

Deskripsi Masalah :

  1. Anda ingin ClassA Anda memiliki variabel kelas ClassB.
  2. Anda menggunakan Objective-C sebagai bahasa pemrograman.
  3. Objective-C tidak mendukung variabel kelas seperti halnya C ++.

Satu alternatif :

Mensimulasikan perilaku variabel kelas menggunakan fitur Objective-C

  1. Deklarasikan / Definisikan variabel statis di dalam classA.m sehingga hanya dapat diakses untuk metode classA (dan semua yang Anda masukkan ke dalam classA.m).

  2. Timpa metode inisialisasi kelas NSObject untuk menginisialisasi variabel statis sekali dengan instance dari ClassB.

  3. Anda akan bertanya-tanya, mengapa saya harus menimpa metode inisialisasi NSObject. Dokumentasi Apple tentang metode ini memiliki jawaban: "runtime mengirimkan inisialisasi ke setiap kelas dalam suatu program tepat satu kali tepat sebelum kelas, atau kelas apa pun yang mewarisi darinya, dikirim pesan pertama dari dalam program. (Demikian metode ini mungkin tidak pernah dipanggil jika kelas tidak digunakan.) "

  4. Jangan ragu untuk menggunakan variabel statis dalam metode class / instance ClassA.

Contoh kode :

file: classA.m

static ClassB *classVariableName = nil;

@implementation ClassA

...
 
+(void) initialize
{
    if (! classVariableName)
        classVariableName = [[ClassB alloc] init];
}

+(void) classMethodName
{
    [classVariableName doSomething]; 
}

-(void) instanceMethodName
{
    [classVariableName doSomething]; 
}

...

@end

Referensi :

  1. Variabel kelas menjelaskan membandingkan pendekatan Objective-C dan C ++
Albaregar
sumber
3
Bisakah Anda memiliki variabel statis Tipe ClassA dalam classA.m?
goatlinks
6
ini mungkin pertanyaan konyol tapi bagaimana dengan pelepasan ingatan itu? tidak masalah karena itu harus hidup selama aplikasi berjalan?
samiq
1
@samiq, periksa Objective-C: Mengapa mempertahankan variabel statis? . Pointer ke objek tidak bisa dihapus, tetapi objek itu sendiri bisa. Anda mungkin tidak ingin melepaskannya karena kemungkinan besar Anda menginginkannya selama aplikasi berjalan, tetapi Anda akan menghemat memori jika Anda melepaskannya, jadi jika Anda tahu Anda tidak membutuhkannya lagi, maka Anda harus lepaskan.
ma11hew28
5
Jika inisialisasi () dijamin akan dipanggil hanya sekali, mengapa Anda memerlukan persyaratan "if (! ClassVariableName)"?
jb
23
@ Jamie, initializedipanggil sekali untuk setiap kelas (superclasses sebelum subclass), tetapi jika subclass tidak menimpa initialize, kelas induk initializeakan dipanggil lagi. Karenanya, seorang penjaga diperlukan jika Anda tidak ingin kode itu dieksekusi dua kali. Lihat Menginisialisasi Objek Kelas di Apple Objective-C docs.
big_m
31

Pada Xcode 8, Anda bisa mendefinisikan properti kelas di Obj-C. Ini telah ditambahkan untuk beroperasi dengan sifat statis Swift.

Objective-C sekarang mendukung properti kelas, yang beroperasi dengan properti tipe Swift. Mereka dinyatakan sebagai: @ properti (kelas) NSString * someStringProperty ;. Mereka tidak pernah disintesis. (23891898)

Berikut ini sebuah contoh

@interface YourClass : NSObject

@property (class, nonatomic, assign) NSInteger currentId;

@end

@implementation YourClass

static NSInteger _currentId = 0;

+ (NSInteger)currentId {
    return _currentId;
}

+ (void)setCurrentId:(NSInteger)newValue {
    _currentId = newValue;
}

@end

Maka Anda dapat mengaksesnya seperti ini:

YourClass.currentId = 1;
val = YourClass.currentId;

Berikut adalah posting penjelasan yang sangat menarik yang saya gunakan sebagai referensi untuk mengedit jawaban lama ini.


2011 Jawaban: (jangan gunakan ini, ini mengerikan)

Jika Anda benar-benar tidak ingin mendeklarasikan variabel global, ada opsi lain, mungkin tidak terlalu ortodoks :-), tetapi berfungsi ... Anda dapat mendeklarasikan metode "get & set" seperti ini, dengan variabel statis di dalam:

+ (NSString*)testHolder:(NSString*)_test {
    static NSString *test;

    if(_test != nil) {
        if(test != nil)
            [test release];
        test = [_test retain];
    }

    // if(test == nil)
    //     test = @"Initialize the var here if you need to";

    return test;
}

Jadi, jika Anda perlu mendapatkan nilainya, telepon saja:

NSString *testVal = [MyClass testHolder:nil]

Dan kemudian, ketika Anda ingin mengaturnya:

[MyClass testHolder:testVal]

Jika Anda ingin dapat mengatur pseudo-static-var ini menjadi nil, Anda dapat mendeklarasikan testHoldersebagai ini:

+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
    static NSString *test;

    if(shouldSet) {
        if(test != nil)
            [test release];
        test = [_test retain];
    }

    return test;
}

Dan dua metode praktis:

+ (NSString*)test {
    return [MyClass testHolderSet:NO newValue:nil];
}

+ (void)setTest:(NSString*)_test {
    [MyClass testHolderSet:YES newValue:_test];
}

Semoga ini bisa membantu! Semoga berhasil.

Gonzalo Larralde
sumber
Keren, tetapi sebenarnya bukan variabel global karena tidak dapat diakses dari .mfile lain , dan saya pikir itu bagus untuk menjadi "global" di dalam Class.mfile.
ma11hew28
29

Pada file .m Anda, Anda dapat mendeklarasikan variabel sebagai statis:

static ClassName *variableName = nil;

Kemudian Anda dapat menginisialisasi pada +(void)initializemetode Anda .

Harap dicatat bahwa ini adalah variabel statis C biasa dan tidak statis dalam arti yang dipertimbangkan oleh Java atau C #, tetapi akan menghasilkan hasil yang serupa.

hal
sumber
16

Di file .m Anda, deklarasikan variabel global file:

static int currentID = 1;

kemudian dalam rutinitas init Anda, rujuk bahwa:

- (id) init
{
    self = [super init];
    if (self != nil) {
        _myID = currentID++; // not thread safe
    }
    return self;
}

atau jika perlu diubah di waktu lain (misalnya dalam metode openConnection Anda), kemudian tambahkan di sana. Ingat itu bukan thread aman seperti ini, Anda harus melakukan sinkronisasi (atau lebih baik lagi, gunakan add atom) jika mungkin ada masalah threading.

Peter N Lewis
sumber
11

Seperti kata pgb, tidak ada "variabel kelas," hanya "variabel instan." Cara objektif-c melakukan variabel kelas adalah variabel global statis di dalam file .m kelas. The "static" memastikan bahwa variabel tidak dapat digunakan di luar file itu (yaitu tidak dapat extern).

Tom Dalling
sumber
3

Ini akan menjadi pilihan:

+(int)getId{
    static int id;
    //Do anything you need to update the ID here
    return id;
}

Perhatikan bahwa metode ini akan menjadi satu-satunya metode untuk mengakses id, jadi Anda harus memperbaruinya dalam kode ini.

Anonim
sumber
2

(Tegasnya bukan jawaban untuk pertanyaan, tetapi dalam pengalaman saya cenderung berguna ketika mencari variabel kelas)

Metode kelas sering dapat memainkan banyak peran yang akan dilakukan oleh variabel kelas dalam bahasa lain (mis. Konfigurasi yang berubah selama pengujian):

@interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
@end
@implementation
+ (NSString*)theNameThing { return @"Something general"; }
- (void)doTheThing {
  [SomeResource changeSomething:[self.class theNameThing]];
}
@end

@interface MySpecialCase: MyCls
@end
@implementation
+ (NSString*)theNameThing { return @"Something specific"; }
@end

Sekarang, objek MyClspanggilan kelas Resource:changeSomething:dengan string @"Something general"pada panggilan ke doTheThing:, tetapi objek berasal dari MySpecialCasedengan string @"Something specific".

Yakub Oscarson
sumber
0

Anda dapat mengubah nama kelas sebagai classA.mm dan menambahkan fitur C ++ di dalamnya.

rd_
sumber
0

Kemungkinan lain adalah memiliki NSNumbersubkelas singleton kecil.

Rudolf Adamkovič
sumber