你真的了解OC中没有真正的私有方法的这句话么

大家一定都听说过一句话,OC中没有任何的真正的私有方法

下边说一下最近的偶然的理解

OC中,.h文件的作用就是向外暴露的 属性 方法 协议 等等都是对外公开的当然属性要看限定词protected、public、private

.m实现了类内部的实现细节,对外是不公开的,m文件内部声明的 属性 方法 协议都是私有的


看下边的代码

//
//  ViewController.h
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import 

@interface ViewController : UIViewController


@end



//
//  ViewController.m
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Class obj = NSClassFromString(@"TTObjc");
    NSObject *ob = [[obj alloc] init];
    SEL methodSel = NSSelectorFromString(@"ppS");
    [ob performSelectorOnMainThread:methodSel withObject:nil waitUntilDone:YES];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end








//
//  TTObjc.h
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import 

@interface TTObjc : NSObject
//-(void)ppS;
@end

//
//  TTObjc.m
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "TTObjc.h"

@implementation TTObjc
-(void)ppS{
    NSLog(@"ppS");
}
@end

注意 TTObjc.h 文件 无论 -(void)ppS;方法是不是被注释掉
控制台输出都是 ** TT22[36247:2692455] ppS**

这也就解释了 OC中没有任何的真正的私有方法

我们只要知道对象的方法名称,即使对象类的.h文件中没有方法声明,也可以调用该方法。

不过当.h 文件没有声明, 通过 [obj method]这么做编译器会报错。

2、通过category做个方法声明也不会引起编译器报错



//
//  ViewController.h
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import 

@interface ViewController : UIViewController


@end



//
//  ViewController.m
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "ViewController.h"
#import "TTObjc.h"
#import "TTObjc+MM.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    TTObjc *tt = [[TTObjc alloc] init];
    [tt ppS];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end





//
//  TTObjc.h
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import 

@interface TTObjc : NSObject
//-(void)ppS;
@end

//
//  TTObjc.m
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "TTObjc.h"

@implementation TTObjc
-(void)ppS{
    NSLog(@"ppS");
}
@end




//
//  TTObjc+MM.h
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "TTObjc.h"

@interface TTObjc (MM)
-(void)ppS;
@end


//
//  TTObjc+MM.m
//  TT22
//
//  Created by jie on 2018/2/25.
//  Copyright © 2018年 jie. All rights reserved.
//

#import "TTObjc+MM.h"

@implementation TTObjc (MM)
//-(void)ppS{
//    NSLog(@"TTObjc+MM    ppS");
//}
@end


通过category这个方式不仅证明了 OC中没有真正的私有方法的

类的.h 没有声明方法的前提。
1)如果category声明的方法和category对用的类方法名相同的相同,并且category实现了这个方法,会调用category的方法
控制台打印 TT22[36478:2715064] TTObjc+MM ppS
2)如果category声明的方法和category对用的类方法名相同的相同,并且category没有实现了这个方法,会去类里边查找这个方法,会调用类的方法
控制台打印 TT22[36535:2720312] ppS


最后说一点题外话,同一个方法在类和category中都有声明和实现,对象调用的时候回调用category的方法实现

为什么会这样,只说一下结论吧,category不是对类的方法覆盖,只是category的方法,在Method查找顺序的前边
这部分涉及到runtime部分,以后会详解解释一下这个Method的查找原理

Git地址 https://github.com/json-zhao/BlogCode/tree/master/blog01

你可能感兴趣的:(你真的了解OC中没有真正的私有方法的这句话么)