Apa yang terjadi jika dua kategori ObjC menggantikan metode yang sama?

Saya mengetahui beberapa aturan mengenai kategori Objective-C:

  1. Metode kategori tidak boleh mengesampingkan metode yang ada (kelas atau instance)
  2. Dua kategori berbeda yang menerapkan metode yang sama untuk kelas yang sama akan menghasilkan perilaku yang tidak terdefinisi

Saya ingin tahu apa yang terjadi ketika saya mengganti salah satu metode kategori saya dalam kategori yang sama. Misalnya:

@interface NSView (MyExtensions)
- (void)foo; // NSView category implementation
@end

@interface MyClass : NSView
{ }
@end

@interface MyClass (MyExtensions)
- (void)foo; // MyClass category implementation
@end

Dengan ditentukannya antarmuka ini, metode mana yang akan dieksekusi ketika saya menjalankan kode berikut?

MyClass * instance = [[MyClass alloc] initWith...];
[instance foo];
[instance release];

Catatan: Dengan kompiler saya, implementasi MyClass diutamakan, tetapi saya tidak yakin apakah hal itu dijamin akan terjadi, atau hanya satu jenis perilaku tidak terdefinisi.


person e.James    schedule 11.07.2010    source sumber


Jawaban (2)


Setiap metode dari setiap kelas memiliki implementasi. Kategori menambah atau mengganti metode untuk kelas tertentu. Itu berarti perilaku yang Anda lihat, di mana MyClass memiliki satu foo dan NSView memiliki foo lainnya, terdefinisi dengan baik. Setiap instance MyClass akan memiliki foo berbeda dari instance NSView apa pun yang bukan MyClass, sama seperti jika foo telah didefinisikan dalam implementasi utama dan bukan sebuah kategori. Anda bahkan dapat memanggil [super foo] dari MyClass untuk mengakses foo yang ditentukan untuk NSView.

person drawnonward    schedule 11.07.2010
comment
Apakah benar mengganti metode Kategori yang dideklarasikan dan diimplementasikan dalam Kategori kelas super? - person BergP; 19.03.2013

Untuk memperluas jawaban yang ditarik ke depan:

Ini masalah hierarki. Kategori sebenarnya hanyalah sarana untuk mengatur file sumber. Saat dikompilasi, semua metode suatu kelas, termasuk metode yang ditentukan dalam kategori apa pun, berakhir di file yang sama.

Apa pun yang dapat Anda lakukan dalam antarmuka kelas reguler dapat Anda lakukan dalam suatu kategori dan apa pun yang tidak boleh Anda lakukan dalam antarmuka kelas reguler tidak boleh Anda lakukan dalam suatu kategori.

So:

Metode kategori tidak boleh mengesampingkan metode yang ada (kelas atau instance)

Anda dapat menggunakan metode yang ditentukan dalam antarmuka kelas reguler untuk mengganti metode yang diwarisi sehingga Anda dapat mengganti metode yang diwarisi dalam suatu kategori.

Namun, Anda tidak akan pernah mencoba memiliki dua definisi metode yang identik dalam antarmuka biasa yang sama sehingga Anda tidak boleh memiliki metode dalam kategori yang memiliki nama yang sama dengan metode dalam antarmuka biasa atau kategori lain di kelas yang sama. Karena semua definisi metode berakhir di file kompilasi yang sama, mereka jelas akan bertabrakan.

Dua kategori berbeda yang menerapkan metode yang sama menghasilkan perilaku yang tidak terdefinisi

Itu harus ditulis ulang menjadi "Dua kategori berbeda yang menerapkan metode yang sama untuk kelas yang sama menghasilkan perilaku yang tidak terdefinisi." Sekali lagi, karena semua metode untuk satu kelas berakhir di file yang sama, memiliki dua metode di kelas yang sama jelas akan menimbulkan keanehan.

Anda dapat menggunakan kategori untuk menyediakan metode yang menggantikan metode superkelas karena kelas dan superkelasnya adalah dua kelas yang berbeda.

Jika Anda pernah bingung apakah suatu kategori akan menimbulkan masalah, tanyakan pada diri Anda ini: "Apakah metode dalam kategori akan berfungsi jika saya menyalin dan menempelkan semuanya ke file .h/.m kelas?" Jika jawabannya "ya", maka Anda aman. Jika "tidak", maka Anda mendapat masalah.

person TechZen    schedule 11.07.2010
comment
+1 Terima kasih. Itu cara yang sangat bagus untuk menggambarkannya. Saya juga telah mengubah kata-kata pada aturan #2 agar sesuai dengan kata-kata Anda. - person e.James; 11.07.2010