标签:
标号 | 主题 | 内容 |
---|---|---|
一 | OC的私有方法 | 私有变量/私有方法 |
二 | @property | 概念/基本使用/寻找方法的过程/查找顺序 |
三 | @synthesize | @synthesize概念/基本使用/注意点 |
四 | id | 静态类型和动态类型/有动态类型原因/id数据类型与静态类型 |
五 | new | new方法实现原理/alloc与init |
六 | 构造方法 | 重写init方法/使用注意/instancetype的作用 |
七 | 自定义构造方法 | 格式/继承中的构造方法 |
八 | 自定义类工厂方法 | 自定义类工厂方法/子父类中的类工厂方法 |
九 | 类的本质 | 类的本质/如何获取类对象/类对象的用法/存储/OC实例对象类对象元数据之间关系 |
@implementation Dog { @public int _age;//在本类中是public,在其他类是private } @end
原则上:私有方法只能在本类的方法中才能调用。
- 注意: OC中没有真正的私有方法 因为OC是消息机制
@interface Dog : NSObject @end @implementation Dog - (void)eat { NSLog(@"啃骨头"); } @end int main(int argc, const char * argv[]) { Dog *d = [Dog new]; SEL s1 = @selector(eat); [d performSelector:s1]; OC中其它调用方式 id *d = [Dog new]; [d eat];//仍可以调用 [d performSelector:@selector(eat)];//仍可以调用 所以说OC中没有真正的私有方法 return 0; }
什么是编译器的指令 ?
@property会让编译器做什么呢? +Xcode之前可以用@property在声明文件中告诉编译器声明成员变量的的访问器(getter/setter)方法
用@property int age;就可以代替下面的两行 - (int)age; // getter - (void)setAge:(int)age; // setter
@property编写步骤
Xcode4.4之后对@property进行了一个增强,只要利用一个@property就可以对getter和setter进行声明和实现
缺陷
注意
.m
中自动生成一个以_开头的私有成员变量
格式
修饰是否生成getter方法的
@property (readonly) int age;
@property (getter = isMarried) BOOL married;说明,通常BOOL类型的属性的getter方法要以is开头
用@synthesize age = _age;就可以代替 - (int)age{ return _age; } - (void)setAge:(int)age{ _age = age; }
@synthesize编写步骤
@interface Person : NSObject { @public int _age; int _number; } @property int age; @end @implementation Person @synthesize age = _number; @end int main(int argc, const char * argv[]) { Person *p = [Person new]; [p setAge:30]; NSLog(@"_number = %i, _age = %i", p->_number, p->_age);//_number = 30,_age = 0 return 0; }
@synthesize age = _age;
@synthesize age;
多个属性可以通过一行@synthesize搞定,多个属性之间用逗号连接
@synthesize age = _age, number = _number, name = _name;
Person *p = [Person new];
动态类型
应用场景
id == NSObject * 是万能指针 id obj = [Person new];
//定义NSObject * 类型 NSObject* obj = [Cat new]; Cat *c = (Cat*)obj; [c eat];
/// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }; /// A pointer to an instance of a class. typedef struct objc_object *id; id obj = [Cat new]; [obj eat]; // 不用强制类型转换 [obj test]; //可以调用私有方法
虽然说id数据类型可以存储任何类型的对象,但是不要养成滥用这种通用类型
动态类型判断类型
(BOOL)isKindOfClass:classObj 判断实例对象是否是这个类或者这个类的子类的实例
Person *p = [Person new]; Student *stu = [Student new]; //判断指定的对象是否是某一个类,或者是某一个类的子类 BOOL res = [p isKindOfClass:[Person class]]; NSLog(@"res = %i", res); // YES res = [stu isKindOfClass:[Person class]]; NSLog(@"res = %i", res); // YES
Person *p = [Person new]; Student *stu = [Student new]; BOOL res = [p isMemberOfClass:[Person class]]; NSLog(@"res = %i", res); // YES res = [stu isMemberOfClass:[Person class]]; NSLog(@"res = %i", res); // NO
BOOL res = [Person isSubclassOfClass:[Student class]]; NSLog(@"res = %i", res); // NO res = [Student isSubclassOfClass:[Person class]]; NSLog(@"res = %i", res); // YES
堆
存储空间,将所有的属性设置为0,返回分配的对象的地址;This method is a combination of alloc and init. Like alloc, it initializes the isa instance variable of the new object so
it points to the class data structure. It then invokes the init method to complete the initialization process.
Person *p1=[person alloc];
Person *p2=[p1 init];
Person *p=[[Person alloc] init];
The isa instance variable of the new instance is initialized to a data structure that describes the class; memory for all other instance variables is set to 0.
An object isn’t ready to be used until it has been initialized. The init method defined in the NSObject class does
no initialization; it simply returns self.
所以下面两句的作用是等价的
Person *p1 = [Person new]; Person *p = [[Person alloc] init];
想在对象创建完毕后,成员变量马上就有一些默认的值就可以重写init方法
重写init方法格式:
- (id)init { self = [super init]; if (self) { //初始化子类 // Initialize self. } return self; }
重写init方法其它格式
- (id)init { //不要把=写成== if (self = [super init]) { // Initialize self. } return self; }
@implementation Person - (instancetype)init { if (self = [super init]) { _age = 10; } return self; } @end
@implementation Person - (instancetype)init { //初始化父类 //如果初始化成功就返回对应的地址,如果失败就返回nil if (self = [super init]) { //设置属性的值 _age = 10; } //返回地址 return self; } @end @implementation Student - (instancetype)init { if (self = [super init]) { _no = 1; } return self; } @end
千万不要把self = [super init]
写成self ==
[super init]
重写构造方法的目的:为了让对象方法一创建出来,成员变量就会有一些固定的值。
// init此时返回值是id NSString *str = [[Person alloc] init]; // Person并没有length方法, 但是id是动态类型, 所以编译时不会报错 NSLog(@"length = %i", str.length); // init此时返回值是instancetype // 由于instancetype它会进行类型检查, 所以编译器会报警告 NSString *str = [[Person alloc] init]; NSLog(@"length = %i", str.length); instancetype *p = [[person alloc] init]; // 错误写法instancetype只能作为返回值
@interface Person : NSObject @property int age; @property NSString *name; // 当想让对象一创建就拥有一些指定的值,就可以使用自定义构造方法 - (id/instancetype)initWithAge:(int)age; - (id/instancetype)initWithName:(NSString *)name; //自定义构造方法可以有1个或者多个参数 - (id/instancetype)initWithAge:(int)age andName:(NSString *)name; @end
@interface Person : NSObject @property int age; - (instancetype)initWithAge:(int)age; @end @interface Student : Person @property NSString *name; - (instancetype)initWithAge:(int)age andName:(NSString *)name; @end @implementation Student - (instancetype)initWithAge:(int)age andName:(NSString *)name andNo:(int)no { /* if (self = [super init]) { // 这个_age是父类中通过property自动在.m中生成的无法继承,不能直接访问 // _age = age; // [self setAge:age]; // _name = name; } return self; */ if(self = [super initWithAge:age andName:name]) { _no = no; } return self; } @end
@interface Person : NSObject @property int age; - (id)initWithAge:(int)age; @end @interface Student : Person @property NSString *name; - (id)initWithAge:(int)age andName:(NSString *)name; @end @implementation Student - (id)initWithAge:(int)age andName:(NSString *)name { if (self = [super initWithAge:age]) { _name = name; } return self; } @end
什么是工厂方法(快速创建方法)
概念
规范
示例
+ (id)person; + (id)person { return [[Person alloc]init]; } + (id)personWithAge:(int)age; + (id)personWithAge:(int)age { Person *p = [[self alloc] init]; [p setAge:age]; return p; }
其实苹果在书写工厂方法时也是按照这样的规划书写
[NSArray array]; [NSArray arrayWithArray:<#(NSArray *)#>]; [NSDictionary dictionary]; [NSDictionary dictionaryWithObject:<#(id)#> forKey:<#(id<NSCopying>)#>]; [NSSet set]; [NSSet setWithObject:<#(id)#>];
由于父类的类工厂方法创建实例对象时是使用父类的类创建的, 所以如果子类调用父类的类工厂方法创建实例对象,创建出来的还是父类的实例对象
示例
@interface Person : NSObject + (id)person; @end @implementation Person + (id)person { return [[Person alloc]init]; } @end @interface Student : Person @property NSString *name; @end @implementation Student @end int main(int argc, const char * argv[]) { Student *stu = [Student person];// [[Person alloc] init] [stu setName:@"lnj"]; // 报错, 因为Person中没有setName }
@interface Person : NSObject + (id)person; @end @implementation Person + (id)person { // return [[Person alloc]init]; // 谁调用这个方法,self就代表谁 // 注意:以后写类方法创建初始化对象,写self不要直接写类名 return [[self alloc]init]; } @end @interface Student : Person @property NSString *name; @end @implementation Student @end int main(int argc, const char * argv[]) { Student *stu = [Student person];// [[Person alloc] init]类工厂方法 [stu setNo];//子类指针指向了父类,将类方法创建初始化对象写self而不要用类名 [stu setName:@"lnj"]; }
格式:[实例对象 class ]; 如: [dog class];
格式:[类名 class]; 如:[Dog class]
[Dog test]; Class c = [Dog class]; [c test];
Dog *g = [Dog new]; Class c = [Dog class]; Dog *g1 = [c new];
Objective-C是一门面向对象的编程语言。
在Xcode中按Shift + Command + O 打开文件搜索框,然后输入NSObject.h和objc.h,可以打开 NSObject的定义头文件,通过头文件我们可以看到,NSObject就是一个包含isa指针的结构体.
NSObject.h @interface NSObject <NSObject> { Class isa OBJC_ISA_AVAILABILITY; } objc.h /// An opaque type that represents an Objective-C class. typedef struct objc_class *Class; /// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };
runtime.h struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
因为类也是一个对象,那它也必须是另一个类的实例,这个类就是元类 (meta class)。
类方法
的列表。当一个类方法
被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有则该元类会向它的父类查找该方法,直到一直找到继承链的头。类方法
的定义是保存在元类(metaclass)中,而方法调用的规则是,如果该类没有一个方法的实现,则向它的父类继续查找。所以为了保证父类的类方法可以在子类中可以被调用,所以子类的元类会继承父类的元类,换而言之,类对象和元类对象有着同样的继承关系。下面这张图或许能够 让大家对isa和继承的关系清楚一些
标签:
原文地址:http://www.cnblogs.com/HMJ-29/p/4690967.html