เทียบเท่ากับวิธีการป้องกันใน Objective-C คืออะไร? ฉันต้องการกำหนดวิธีการที่เฉพาะคลาสที่ได้รับเท่านั้นที่สามารถเรียก / ใช้งานได้
เทียบเท่ากับวิธีการป้องกันใน Objective-C คืออะไร? ฉันต้องการกำหนดวิธีการที่เฉพาะคลาสที่ได้รับเท่านั้นที่สามารถเรียก / ใช้งานได้
คำตอบ:
คุณไม่สามารถประกาศวิธีการป้องกันหรือเป็นส่วนตัวได้ ลักษณะไดนามิกของ Objective-C ทำให้ไม่สามารถใช้การควบคุมการเข้าถึงสำหรับวิธีการได้ (คุณสามารถทำได้โดยการปรับเปลี่ยนคอมไพเลอร์หรือรันไทม์อย่างหนักด้วยการลงโทษความเร็วที่รุนแรง แต่ด้วยเหตุผลที่ชัดเจนจึงไม่สามารถทำได้)
คุณสามารถจำลองการเข้าถึงวิธีการที่มีการป้องกันและแบบส่วนตัวได้โดยทำดังต่อไปนี้:
การป้องกันเหล่านี้ไม่ได้เป็นไปตามที่ Sachin ระบุไว้บังคับใช้ที่รันไทม์ (เช่นใน Java เป็นต้น)
UIGestureRecognizerSubclass.h
นี่คือสิ่งที่ฉันทำเพื่อให้เมธอดป้องกันมองเห็นได้สำหรับคลาสย่อยของฉันโดยไม่ต้องใช้เมธอด นั่นหมายความว่าฉันไม่ได้รับคำเตือนของคอมไพเลอร์ในคลาสย่อยของฉันเกี่ยวกับการใช้งานที่ไม่สมบูรณ์
SuperClassProtectedMethods.h (ไฟล์โปรโตคอล):
@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end
@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end
SuperClass.m: (ตอนนี้คอมไพเลอร์จะบังคับให้คุณเพิ่มวิธีการป้องกัน)
#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.
performSelector
กับมัน
[(id)obj hiddenMethod]
นอกจากนี้คุณยังสามารถทำ พูดอย่างถูกต้องว่า Objective-C ไม่รองรับวิธีการป้องกัน
ฉันเพิ่งค้นพบสิ่งนี้และใช้ได้กับฉันเพื่อปรับปรุงคำตอบของอดัมในซูเปอร์คลาสของคุณให้ใช้วิธีการป้องกันในไฟล์. m แต่อย่าประกาศเป็นไฟล์. h ในคลาสย่อยของคุณให้สร้างหมวดหมู่ใหม่ในไฟล์. m ของคุณด้วยการประกาศวิธีการป้องกันของซูเปอร์คลาสและคุณสามารถใช้วิธีการป้องกันของซูเปอร์คลาสในคลาสย่อยของคุณได้ ในที่สุดสิ่งนี้จะไม่ป้องกันผู้เรียกใช้เมธอดที่ได้รับการป้องกันหากถูกบังคับขณะรันไทม์
/////// 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
protectedMethod
อีกวิธีหนึ่งโดยใช้ตัวแปร @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
คุณสามารถกำหนดเมธอดเป็นเมธอดส่วนตัวของคลาสพาเรนต์และสามารถใช้[super performSelector:@selector(privateMethod)];
ในคลาสลูกได้
คุณสามารถจัดเรียงได้ด้วยหมวดหมู่
@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
เมธอดจะไม่ถูกซ่อนหากคุณนำเข้าหมวดหมู่ในคลาสอื่น แต่คุณไม่ได้ทำ เนื่องจากลักษณะไดนามิกของ Objective-C เป็นไปไม่ได้ที่จะซ่อนเมธอดอย่างสมบูรณ์โดยไม่คำนึงถึงประเภทอินสแตนซ์การโทร
วิธีที่ดีที่สุดที่จะไปน่าจะเป็นหมวดหมู่ต่อเนื่องของคลาสตามที่ @Brian Westphal ตอบ แต่คุณจะต้องกำหนดวิธีการในหมวดหมู่นี้ใหม่สำหรับแต่ละอินสแตนซ์ย่อย
ทางเลือกหนึ่งคือใช้ส่วนขยายคลาสเพื่อซ่อนเมธอด
ใน.h
:
@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
ใน.m
:
@interface SomeAppDelegate()
- (void)localMethod;
@end
@implementation SomeAppDelegate
- (void)localMethod
{
}
@end
@interface
ประกาศในไฟล์. m ด้วยซ้ำ คุณสามารถประกาศฟังก์ชันและใช้งานได้และจะถือว่าเป็นส่วนตัว
ฉันมักจะตั้งชื่อวิธีการป้องกันด้วยคำนำหน้าภายใน:
-(void) internalMethod;