Metode yang dilindungi di Objective-C

112

Apa yang setara dengan metode yang dilindungi di Objective-C? Saya ingin mendefinisikan metode yang hanya dapat dipanggil / diterapkan oleh kelas turunan.

LK.
sumber

Jawaban:

47

Anda tidak dapat mendeklarasikan metode dilindungi atau pribadi. Sifat dinamis Objective-C membuatnya tidak mungkin untuk mengimplementasikan kontrol akses untuk metode. (Anda dapat melakukannya dengan banyak memodifikasi kompiler atau runtime, dengan penalti kecepatan yang parah, tetapi untuk alasan yang jelas hal ini tidak dilakukan.)

Diambil dari Sumber .

Sachin Shanbhag
sumber
Meskipun secara teknis Anda tidak bisa, Anda dapat meniru variabel privat.
Sharen Eayrs
Lee - jika Anda mendeklarasikan fungsi pointer di @protected dan menetapkan fungsi dalam metode init apakah akan berhasil?
bikram990
156

Anda dapat menyimulasikan akses yang dilindungi dan privat ke metode dengan melakukan hal berikut:

  • Deklarasikan metode pribadi Anda dalam ekstensi kelas (yaitu kategori tanpa nama yang dideklarasikan di dekat bagian atas file '.m kelas)
  • Deklarasikan metode terlindungi Anda dalam header Subclass - Apple menggunakan pola ini sehubungan dengan UIGestureRecognizer (lihat dokumentasi dan referensi ke UIGestureRecognizerSubclass.h)

Perlindungan ini, seperti yang dicatat Sachin, tidak diberlakukan pada waktu proses (seperti yang ada di Java, misalnya).

Brian Westphal
sumber
2
Tentang solusi mirip UIGestureRecognizer: Masalahnya adalah jika beberapa kode mengimpor subkelas, ia juga akan mengimpor header Subclass dan karenanya akan memiliki akses ke metode "dilindungi". Apakah ada jalan keluarnya?
yonix
5
Hai yonix, impor untuk subclass header akan dilakukan di dalam file .m bukan di dalam file .h, jadi mengimpor subclass tidak akan mengimpor metode yang dilindungi ini.
Brian Westphalia
Saran Keren Brian, terima kasih banyak !! Ke poster asli, untuk properti yang dideklarasikan, cukup pastikan bahwa Anda menggunakan @dynamic dalam implementasi ekstensi kelas subkelas (kategori tanpa nama), sehingga pada waktu proses, implementasi kelas induk akan digunakan
user1046037
1
Bagaimana cara melihat UIGestureRecognizerSubclass.h?
Sharen Eayrs
5
Terima kasih telah menunjukkan tentang bagaimana Apple melakukannya secara internal. Saya memposting contoh lengkap tentang cara menerapkan hal-hal dengan cara yang sama seperti yang dilakukan AppleUIGestureRecognizerSubclass.h
Dirty Henry
14

Inilah yang saya lakukan untuk membuat metode terlindungi terlihat oleh subkelas saya, tanpa mengharuskan mereka untuk menerapkan metode itu sendiri. Ini berarti saya tidak mendapatkan peringatan compiler di subclass saya tentang implementasi yang tidak lengkap.

SuperClassProtectedMethods.h (file protokol):

@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end

@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end

SuperClass.m: (compiler sekarang akan memaksa Anda untuk menambahkan metode yang dilindungi)

#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
@end

SubKelas.m:

#import "SuperClassProtectedMethods.h"
// Subclass can now call the protected methods, but no external classes importing .h files will be able to see the protected methods.
Michael Kernahan
sumber
2
Arti dilindungi adalah tidak bisa disebut secara eksternal. Anda masih dapat memanggil metode apa pun yang ditentukan di kelas terlepas dari apakah metode tersebut terlihat secara eksternal atau tidak.
eonil
Ya, saya mengerti ini. Metode ini bekerja untuk otak manusia, bukan kode yang sebenarnya dikompilasi. Tapi Objective-C tidak mengizinkannya (tidak bisa menelepon secara eksternal). Anda selalu bisa performSelectormelakukannya.
Michael Kernahan
1
Anda juga bisa melakukannya [(id)obj hiddenMethod]. Tepatnya, metode yang dilindungi tidak didukung di Objective-C.
eonil
Masalahnya adalah yang Anda sebut kelas terlindungi tidak dapat mengiklankan properti. Jika Anda tidak membutuhkan properti, maka siapa pun sangat menyadari bahwa Anda dapat menambahkan kategori yang dilindungi.
Sharen Eayrs
@eonil: "Anda juga dapat melakukan [(id) obj hiddenMethod]." Ya, Anda dapat melakukannya, tetapi Anda akan mendapatkan peringatan dari kompiler, jika metode itu tidak ada dalam antarmuka yang disertakan.
Kaiserludi
9

Saya baru saja menemukan ini dan itu berhasil untuk saya. Untuk memperbaiki jawaban Adam, dalam superclass Anda membuat implementasi metode yang dilindungi dalam file .m tetapi jangan mendeklarasikannya dalam file .h. Dalam subkelas Anda, buat kategori baru di file .m Anda dengan deklarasi metode superkelas yang dilindungi dan Anda dapat menggunakan metode kelas super yang dilindungi di subkelas Anda. Ini pada akhirnya tidak akan mencegah pemanggil dari metode yang seharusnya dilindungi jika dipaksa pada waktu proses.

/////// SuperClass.h
@interface SuperClass

@end

/////// SuperClass.m
@implementation SuperClass
- (void) protectedMethod
{}
@end

/////// SubClass.h
@interface SubClass : SuperClass
@end

/////// SubClass.m
@interface SubClass (Protected)
- (void) protectedMethod ;
@end

@implementation SubClass
- (void) callerOfProtectedMethod
{
  [self protectedMethod] ; // this will not generate warning
} 
@end
redwud
sumber
2
Dalam hal ini compiler masih memberikan peringatan tentang protectedMethod
unimplemented
Ini adalah penyelesaian yang bagus tetapi alih-alih membuat kategori (Dilindungi), Anda dapat membuat ekstensi.
Dharmesh Siddhpura
@skywinder Mungkin itu terjadi di versi sebelumnya, tetapi versi Xcode saat ini tidak memiliki masalah dengan solusi ini.
Darren Ehlers
2

Cara lain menggunakan variabel @protected.

@interface SuperClass:NSObject{
  @protected
    SEL protectedMehodSelector;
}

- (void) hackIt;
@end

@implementation SuperClass

-(id)init{

self = [super init];
if(self) {
 protectedMethodSelector = @selector(baseHandling);
 }

return self;
}

- (void) baseHandling {

  // execute your code here
}

-(void) hackIt {

  [self performSelector: protectedMethodSelector];
}

@end

@interface SubClass:SuperClass
@end

@implementation SubClass

-(id)init{

self = [super init];
if(self) {
 protectedMethodSelector = @selector(customHandling);
 }

return self;
}

- (void) customHandling {

  // execute your custom code here
}

@end
marius bardan
sumber
dan Anda dapat meletakkan IVars yang dilindungi dalam ekstensi kelas di file header bernama dilindungi juga
malhal
1

Anda bisa mendefinisikan metode sebagai metode privat dari kelas induk dan bisa digunakan [super performSelector:@selector(privateMethod)];di kelas anak.

chinthakad.dll
sumber
0

Anda dapat semacam melakukan hal ini dengan kategori.

@interface SomeClass (Protected)
-(void)doMadProtectedThings;
@end

@implementation SomeClass (Protected)

- (void)doMadProtectedThings{
    NSLog(@"As long as the .h isn't imported into a class of completely different family, these methods will never be seen. You have to import this header into the subclasses of the super instance though.");
}

@end

Metode tidak disembunyikan jika Anda mengimpor kategori di kelas lain, tetapi Anda tidak melakukannya. Karena sifat dinamis Objective-C, sebenarnya tidak mungkin untuk menyembunyikan metode sepenuhnya terlepas dari jenis instance pemanggil.

Cara terbaik untuk melakukannya mungkin adalah kategori kelanjutan kelas seperti yang dijawab oleh @Brian Westphal tetapi Anda harus mendefinisikan ulang metode dalam kategori ini untuk setiap instance subclass.

Adam Waite
sumber
0

Salah satu opsinya adalah menggunakan ekstensi kelas untuk menyembunyikan metode.

Masuk .h:

@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

Masuk .m:

@interface SomeAppDelegate()
- (void)localMethod;
@end

@implementation SomeAppDelegate

- (void)localMethod
{
}

@end
ohho
sumber
Saya rasa Anda bahkan tidak memerlukan @interfacedeklarasi dalam file .m. Anda bisa mendeklarasikan fungsi dan menggunakannya dan itu akan diperlakukan sebagai privat.
Russ
1
Perhatikan bahwa ini benar hanya dengan pembaruan terkini di Objective C. Sebelum itu, Anda harus mendeklarasikan metode dalam antarmuka jika tidak, Anda setidaknya akan mendapatkan peringatan.
Guillaume Laurent
0

Saya biasanya memberi nama metode yang dilindungi dengan awalan internal:

-(void) internalMethod;
lbsweek
sumber