您的位置:首页 > 移动开发 > Objective-C

为什么说 Objective-C 没有私有方法和私有变量

2016-12-09 16:24 295 查看


为什么说 Objective-C 没有私有方法和私有变量

之前在某个地方看到说 Objective-C 并没有绝对的私有变量和私有方法。开始挺纳闷的。我们在 .m 中实现的方法,不在.h 中声明,外界不就不能访问到了吗?

首先,我们先来看一下私有的定义:私有是指只能够在本类内部使用或访问,但是不能在类的外部被访问。

看起来好像没有什么问题,不过以下的几种方式的确打破了上面的规则。


访问私有方法

在 Objective-C 中,对象调用方法是以发送消息的形式实现的。所有方法的调用最终都会转化为发送消息的形式,原型如下:
id objc_msgSend(id self, SEL op, ...)


我们定义如下两个类,实现子类访问父类的 "私有方法"。
#import <objc/message.h>
// MMFather.h
@interface MMFather : NSObject
@end
// MMFather.m
@implementation MMFather
(void)run:(NSString *)param {
NSLog(@"Father run with %@", param);
}
@end

// MMSon.h
@interface MMSon : MMFather
@end
// MMSon.m
@implementation MMSon
@end
​

// main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
MMSon *son = [MMSon new];
​
// 方法一

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
objc_msgSend(son, @selector(run:), @"iPhone");
#pragma clang diagnostic pop
​
// 方法二

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
if ([son respondsToSelector:@selector(run:)]) {
[son performSelector:@selector(run:) withObject:@"iPhone"];
}
#pragma clang diagnostic pop
​      }
return 0;
}
≈


我们声明了两个类,一个 MMFather 类,一个继承自 MMFather 的 MMSon 类。在 MMFather.m 中实现 
run:
 方法,但是并没有在
MMFather.h 中公开。如果我们直接使用 Son 实例调用 run 方法编译器会报错。

但是我们使用上述两种方法都能成功实现对父类私有方法的访问。"-Wundeclared-selector" 是为了消除编译器找不到方法的警告,该方式只能在确认某个方式实现的前提下使用,否者会在运行时奔溃。

Objective-C 为什么能够实现访问「私有方法」呢?其实这跟 Objective-C 语言的动态特性有密切的关系,对象在运行的时候才会去查找方法。Objective-C 对象有一个 isa 指针指向其父类,在向该实例发送消息的时候,若它自己不能识别回到父类中去查找该消息。

如下如所示:



objective-c_message.png

具体有关 Objective-C 对象模型的知识可以参看这篇:Objective-C对象模型及应用


访问私有变量

私有变量的定义类似私有方法,但是在 Objective-C 中,仍然可以通过 runtime 来实现对私有变量的访问。

在 MMSon.m 中加入一个私有方法,在 main.m 中访问:
@implementation MMFather {
NSString *_name;
}

// main.m
{
MMSon *son = [[MMSon alloc] initWithName:@"小白"];
Ivar nameIvar = class_getInstanceVariable([son class], "_name");
NSString *name = object_getIvar(son, nameIvar);
NSLog(@"son name: %@", name);
}


控制台成功的打印出了:小白

综上所述:Objective-C 的确是没有绝对的私有方法和私有变量的,也这是因为 OC 的这种特性,可以让开发者做更多 trick 的事。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: