Mengganti metode menggunakan kategori di Objective-C

87

Dapatkah saya menggunakan kategori kelas untuk menimpa metode yang sudah diimplementasikan menggunakan kategori? Seperti ini:

1) Metode asli

-(BOOL) method {
  return true;
}

2) Metode yang diganti

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Apakah ini akan berhasil, atau apakah ini ilegal?

retix
sumber

Jawaban:

147

Dari dokumentasi Apple :

Meskipun bahasa Objective-C saat ini memungkinkan Anda menggunakan kategori untuk mengganti metode yang diwarisi oleh kelas, atau bahkan metode yang dideklarasikan dalam antarmuka kelas, Anda sangat tidak disarankan untuk melakukannya . Kategori bukanlah pengganti subclass. Ada beberapa kekurangan signifikan dalam menggunakan kategori untuk mengganti metode:

  • Saat kategori mengganti metode yang diwariskan, metode dalam kategori tersebut dapat, seperti biasa, menjalankan implementasi yang diwariskan melalui pesan ke super. Namun, jika sebuah kategori menimpa metode yang ada di kelas kategori tersebut, tidak ada cara untuk memanggil implementasi asli .

  • Kategori tidak dapat dengan andal mengganti metode yang dideklarasikan dalam kategori lain dari kelas yang sama.

    Masalah ini sangat penting karena banyak kelas Kakao diimplementasikan dengan menggunakan kategori. Metode yang ditentukan kerangka kerja yang Anda coba timpa mungkin telah diterapkan dalam kategori, sehingga penerapan mana yang diutamakan tidak ditentukan.

  • Kehadiran beberapa metode kategori dapat menyebabkan perubahan perilaku di semua kerangka kerja. Misalnya, jika Anda mengganti windowWillClose:metode delegasi dalam kategori di NSObject, semua delegasi jendela di program Anda kemudian merespons menggunakan metode kategori; perilaku semua instance NSWindow Anda dapat berubah. Kategori yang Anda tambahkan pada kelas framework dapat menyebabkan perubahan misterius dalam perilaku dan menyebabkan error.

Benoît
sumber
Terima kasih tapi saya sudah tahu itu. Saya hanya ingin tahu apakah kasus saya legal atau tidak. Kasus saya sedikit berbeda dari dokumen. :)
retix
Mengapa berbeda? Dokter mengatakan bahwa itu legal JIKA metode asli tidak ada dalam kategori, tetapi sangat tidak disarankan. Kemudian Anda dapat melakukannya ...
Benoît
1
Terima kasih atas sarannya. Saya miskin dalam bahasa ini. Saya mendapat informasi baru dari Anda.
retix
1
Apakah benar untuk mengganti dalam metode Kategori yang dideklarasikan dan diimplementasikan dalam Kategori kelas super?
BergP
2
Tautan rusak, apakah ini versi baru? developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
RndmTsk
18

Anda dapat melakukannya dengan mengadaptasi pendekatan Class Cluster , atau menggunakan metode swizzling .

Jika tidak, perilaku dua atau lebih metode yang dikategorikan tidak dapat ditentukan

Martin Babacaev
sumber
9

Tautan dokumentasi lama sudah mati; pengganti terbaik yang bisa saya temukan ada di sini: Apple Docs :

Hindari Bentrokan Nama Metode Kategori

Karena metode yang dideklarasikan dalam kategori ditambahkan ke kelas yang sudah ada, Anda harus sangat berhati-hati tentang nama metode.

Jika nama metode yang dideklarasikan dalam kategori sama dengan metode di kelas aslinya, atau metode di kategori lain di kelas yang sama (atau bahkan superclass), perilaku tidak ditentukan untuk implementasi metode mana yang digunakan di runtime. Hal ini kecil kemungkinannya menjadi masalah jika Anda menggunakan kategori dengan kelas Anda sendiri, tetapi dapat menyebabkan masalah saat menggunakan kategori untuk menambahkan metode ke kelas standar Cocoa atau Cocoa Touch.

Ini Apple menggunakan sentuhan yang lebih ringan, tetapi poin utamanya sama: Anda mengundang bencana, karena perilaku yang tidak terduga adalah diam.

AmitaiB
sumber
2

Penting untuk dicatat bahwa kategori juga dapat digunakan untuk mengganti metode yang ada di kelas dasar (misalnya, metode penggerak kelas Car), tetapi Anda tidak boleh melakukan ini. Masalahnya adalah bahwa kategori adalah struktur organisasi yang datar. Jika Anda mengganti metode yang ada di Car + Maintenance.m, dan kemudian memutuskan ingin mengubah perilakunya lagi dengan kategori lain, tidak ada cara untuk Objective-C mengetahui implementasi mana yang akan digunakan. Subclassing hampir selalu merupakan pilihan yang lebih baik dalam situasi seperti ini.

Dari tutorial ini, http://rypress.com/tutorials/objective-c/categories

Vinuta
sumber