Objective-C'de korumalı yöntemler


112

Objective-C'deki korumalı yöntemlerin eşdeğeri nedir? Yalnızca türetilmiş sınıfların çağırabileceği / uygulayabileceği yöntemleri tanımlamak istiyorum.

Yanıtlar:


47

Korunan veya özel bir yöntemi de bildiremezsiniz . Objective-C'nin dinamik yapısı, yöntemler için erişim kontrollerinin uygulanmasını imkansız kılar. (Bunu, ciddi bir hız cezası ile derleyiciyi veya çalışma zamanını büyük ölçüde değiştirerek yapabilirsiniz, ancak bariz nedenlerden dolayı bu yapılmaz.)

Kaynaktan Alındı .


Teknik olarak yapamazken, özel değişkenleri taklit edebilirsiniz.
Sharen Eayrs

Lee - @protected'da bir işlev işaretçisi bildirirseniz ve init yöntemine bir işlev atarsanız çalışır mı?
bikram990

156

Aşağıdakileri yaparak yöntemlere korumalı ve özel erişimi simüle edebilirsiniz :

  • Özel yöntemlerinizi bir sınıf uzantısında bildirin (yani, sınıf '.m dosyasının üst kısmına yakın bir adsız kategori bildirimi)
  • Korumalı yöntemlerinizi bir Subclass üstbilgisinde beyan edin - Apple, bu kalıbı UIGestureRecognizer ile ilgili olarak kullanır (UIGestureRecognizerSubclass.h belgelerine ve referansına bakın)

Bu korumalar, Sachin'in belirttiği gibi, çalışma zamanında uygulanmaz (örneğin Java'da olduğu gibi).


2
UIGestureRecognizer benzeri çözüm hakkında: Sorun, eğer bazı kodlar alt sınıfı içe aktarırsa, Alt Sınıf başlığını da içe aktaracak ve bu nedenle "korumalı" yöntemlere erişebilecek olmasıdır. Bunun bir yolu var mı?
yonix

5
Merhaba yonix, alt sınıf üstbilgisinin içe aktarılması .h dosyasının içinde değil .m dosyasının içinde yapılacak, bu nedenle alt sınıfın içe aktarılması bu korumalı yöntemleri içe aktarmayacaktır.
Brian Westphal

Harika Öneri Brian, çok teşekkürler !! Orijinal postere, bildirilen özellikler için, alt sınıfın sınıf uzantısı (adsız kategori) uygulamasında @dynamic'i kullandığınızdan emin olun, böylece çalışma zamanında üst sınıfın uygulaması kullanılacaktır
user1046037

1
UIGestureRecognizerSubclass.h'yi nasıl görebilirim?
Sharen Eayrs

5
Apple'ın bunu dahili olarak nasıl yaptığına işaret ettiğiniz için teşekkür ederiz. Ben tam bir örnek yayınlanmıştır Stuff Elma yok aynı şekilde nasıl uygulanacağıUIGestureRecognizerSubclass.h
Kirli Henry

14

Yöntemleri kendilerinin uygulamalarını gerektirmeden, alt sınıflarım tarafından görünür hale getirmek için yaptığım şey şu. Bu, alt sınıfımda eksik bir uygulamaya sahip olma konusunda derleyici uyarıları almadığım anlamına geliyordu.

SuperClassProtectedMethods.h (protokol dosyası):

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

@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end

SuperClass.m: (derleyici şimdi sizi korumalı yöntemler eklemeye zorlayacaktır)

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

SubClass.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.

2
Anlamı korumalı öyle olduğunu mümkün değil dışarıdan çağrılacak. Dışarıdan görünür olup olmadıklarına bakılmaksızın, sınıfta tanımlanan herhangi bir yöntemi yine de çağırabilirsiniz.
eonil

Evet, bunu anlıyorum. Bu yöntem, gerçek derlenmiş kod için değil, insan beyni için çalışır. Ancak Objective-C buna izin vermez (dışarıdan arayamama). Her zaman yapabilirsin performSelector.
Michael Kernahan

1
Sen de yapabilirsin [(id)obj hiddenMethod]. Doğru söylemek gerekirse, korumalı yöntem Objective-C'de desteklenmez.
eonil

Bununla ilgili sorun, sözde korumalı sınıflarınızın özellikleri reklamlayamamasıdır. Özelliklere ihtiyacınız yoksa, korunan kategorileri kolayca ekleyebileceğinizi herkes bilir.
Sharen Eayrs

@eonil: "Ayrıca [(id) obj hiddenMethod] da yapabilirsiniz." Evet, bunu yapabilirsiniz, ancak bu yöntem dahil edilen herhangi bir arayüzde değilse derleyiciden bir uyarı alırsınız.
Kaiserludi

9

Bunu yeni keşfettim ve benim için işe yarıyor. Adam'ın cevabını geliştirmek için, üst sınıfınızda korumalı yöntemin .m dosyasında bir uygulamasını yapın, ancak bunu .h dosyasında bildirmeyin. Alt sınıfınızda, üst sınıfın korumalı yönteminin bildirimi ile .m dosyanızda yeni bir kategori oluşturun ve alt sınıfınızdaki üst sınıfın korumalı yöntemini kullanabilirsiniz. Bu, çalışma zamanında zorlanırsa, sözde korumalı yöntemi arayan kişiyi nihai olarak engellemeyecektir.

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

2
Bu durumda, derleyici hala uygulanmayan yöntem hakkında uyarı protectedMethod
veriyor

Bu iyi bir çalışma, ancak bir kategori (Korumalı) yapmak yerine bir uzantı oluşturabilirsiniz.
Dharmesh Siddhpura

@skywinder Belki daha önceki bir sürümde yaptı, ancak Xcode'un mevcut sürümlerinin bu çözümle bir sorunu yok.
Darren Ehlers

2

@ Korumalı değişkenleri kullanmanın başka bir yolu.

@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

ve korumalı IVar'ları bir sınıf uzantısına da korumalı adlı bir başlık dosyasına
koyabilirsiniz

1

Yöntemi, ana sınıfın özel bir yöntemi olarak tanımlayabilir [super performSelector:@selector(privateMethod)];ve alt sınıfta kullanabilirsiniz.


0

Şunları yapabilirsiniz çeşit bir kategori ile yapıyoruz.

@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

Kategoriyi başka bir sınıfa aktarırsanız yöntemler gizlenmez, ancak bunu yapmazsınız. Objective-C'nin dinamik doğası nedeniyle, çağıran örnek türünden bağımsız olarak bir yöntemi tamamen gizlemek aslında imkansızdır.

Gitmenin en iyi yolu muhtemelen @ Brian Westphalia tarafından yanıtlanan sınıf devam kategorisidir, ancak bu kategorideki yöntemi her bir alt sınıf örneği için yeniden tanımlamanız gerekir.


0

Bir seçenek, sınıf uzantısı kullanmaktırYöntemlerden yöntemleri gizlemek .

İçinde .h:

@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

İçinde .m:

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

@implementation SomeAppDelegate

- (void)localMethod
{
}

@end

@interface.M dosyasındaki beyana ihtiyacınız olduğunu bile sanmıyorum . Sadece bir fonksiyon tanımlayabilir ve onu kullanabilirsiniz ve özel olarak kabul edilecektir.
Russ

1
Bunun yalnızca Hedef C'deki son güncellemelerde geçerli olduğunu unutmayın. Bundan önce, yöntemi bir arayüzde bildirmeniz gerekiyordu, aksi takdirde en azından bir uyarı alırsınız.
Guillaume Laurent

0

Genellikle korumalı yöntemi dahili önekle adlandırırım:

-(void) internalMethod;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.