OC核心语法
来源:互联网 发布:淘宝客机器人 编辑:程序博客网 时间:2024/05/01 14:25
一、点语法
点语法的本质是方法调用,就是调用的setter和getter方法。
#import <Foundation/Foundation.h>#import "Person.h"int main(){ Person *p=[Person new]; p.age=23; // 这就是点语法,xcode会自动将这个代码转为[p setAge:23] NSLog(@"%d",p.age); // xcode会自动将点语法转为[p age] return 0;}//编译器根据取值还是赋值来判断转为setter还是getter。@interface Person : NSObject{ int _age;}- (void)setAge:(int)age;- (int)age;@end@implementation Person- (void)setAge:(int)age{ _age=age; // self.age=age; 这会死循环 NSLog(@"use-setter");//为了验证点语法是否调用setter方法}- (int)age{ NSLog(@"use-getter");//为了验证点语法是否覅用getter方法 //NSLog(@"%d",self.age);这会死循环,get方法不停地调用自己 return _age;}@end
@private:只能在当前类的对象方法中直接访问。类的实现中的变量默认是private
@protected:可以在当前类以及子类的对象方法中直接访问。类的声明中的变量默认是protect。
@public:任何地方都可以直接访问
@package:同一个“体系内”(框架)可以访问,介于@private和@public之间
OC只支持单继承。
#import <Foundation/Foundation.h>
//Person类@interface Person : NSObject{ @protected int _age; @private NSString *_name;}- (void)setAge:(int)age;- (int)age;- (void)setName:(NSString *)name;- (NSString *)name;@end@implementation Person{ int hight; // 在类的实现中定义了一个变量,这个变量是private,其他类均不能访问。}//_age的set和get- (void)setAge:(int)age{ NSLog(@"%d",self->hight); //本类可以直接访问hight _age=age; // self.age=age; 这会死循环 NSLog(@"use-setter");//为了验证点语法是否调用setter方法}- (int)age{ NSLog(@"use-getter");//为了验证点语法是否覅用getter方法 //NSLog(@"%d",self.age);这会死循环,get方法不停地调用自己 return _age;}//_name的set和get- (void)setName:(NSString *)name{ _name=name;}- (NSString *)name{ return _name;}@end
//Student类@interface Student : Person- (void)said;@end@implementation Student- (void)said{ /* NSLog(@"my name is %@",self->_name); 这样是错误的,因为_name是Person中被private修饰的,子类不能直接访问. 但是Student类中有_name这个变量 */ NSLog(@"my name is %@,age is %d",self.name,self->_age); // _age可以被子类直接访问 // NSLog(@"%d",self->hight); 这是错误的,因为Person.h中根本没有hight这个变量}@endint main(){ Person *p=[Person new]; p.age=23; // 这就是点语法,xcode会自动将这个代码转为[p setAge:23] NSLog(@"%d",p.age); // xcode会自动将点语法转为[p age] //private修饰的变量虽然子类不能直接访问,但是在子类内部这些变量都有 Student *student=[Student new]; student.age=12; student.name=@"xiaoming"; [student said]; return 0;}
三、@property和@synthesize
@property:自动生成某个成员变量的setter和getter方法的声明
如:@property int age;
编译器会自动将这句自动生成 -(void)setAge:(int)age;
和 -(int)age;
#import <Foundation/Foundation.h>#import "Person.h"int main(){ Person *p=[Person new]; p.age=23; // 这就是点语法,xcode会自动将这个代码转为[p setAge:23] NSLog(@"%d",p.age); // xcode会自动将点语法转为[p age] [p setName:@"liming"]; NSLog(@"%@",[p name]); return 0;}@interface Person : NSObject{ int _age; NSString *_name;}@property int age;/* int 就是set方法的参数类型和get方法的返回值类型, age 直接影响到set和get方法的名称 假如 @property int _age; 那么生成的set和get方法将分别是 -(void)set_age:(int)_age; - (int)_age; */@property NSString * name;@end@implementation Person//_age的set和get- (void)setAge:(int)age{ _age=age;;}- (int)age{ return _age;}//_name的set和get- (void)setName:(NSString *)name{ _name=name;}- (NSString *)name{ return _name;}@end
@synthesize:自动生成某个成员变量的set和get方法实现
如:@synthesize age=_age;(age:@property里写的是啥,这里就写啥。_age:这个变量写成什么,set和 get里面就会访问什么变量)
这句话意味着会访问_age这个变量。
因此上述代码中的Person类的实现可以写成:
@implementation Person//_age的set和get@synthesize age=_age;//_name的set和get@synthesize name=_name;// @synthesize age=_age,name=_name;这可以连着写//@property 也可以连着写 @proerty int age,hight; (age和hight必须都是int类型)@end
@synthesize age=_age;这句代码访问_age这个变量,如果不存在,那就会自动生成一个@private类型的_age变量。
所以上述代码可以简化为:
#import <Foundation/Foundation.h>@interface Person : NSObject //类的声明//自动生成相应的set和get方法声明@property int age;@property NSString * name;@end@implementation Person // 类的实现//自动生成变量_age和_name.且自动生成相应的get和set方法的实现@synthesize age=_age,name=_name;@end
随着xcode不断升级,@synthesize语句也可以简化不写
因此代码能进一步简化到:
#import <Foundation/Foundation.h>//类的声明@interface Person : NSObject//自动生成相应的set和get方法声明,同时也实现了这些方法,而且还自动生成了私有的_age和_name@property int age;@property NSString * name;@end//类的实现@implementation Person@end
注意:1.@synthesize age;这里没有注明访问哪个变量,那么就会默认访问跟age一样的变量,也就是会访问成员变 量age而不是_age。假如age这个变量不存在,就会自动生成age。
2.代码中没有相应的set和get方法时,Xcode才会自动生成。有,就不生成,同时变量也不会生成(因为生成 变量的目的就是为了在set和get中使用)。
若手动实现了setter方法,编译器就只会自动生成getter方法
若手动实现了getter方法,编译器就只会自动生成setter方法
若同时手动实现了setter和getter方法,编译器就不会自动生成不存在的成员变量
四、id类型
万能指针,能指向任何OC对象,相当于NSObject *注意:id后面不要加上*
id p = [Person new];
五、构造方法
构造方法是用来初始化对象的方法。
重写构造方法
完整地创建一个可用的对象,分为两步:
1>分配存储空间 (类方法:+(id)alloc,返回一个分配好内存空间的对象,但是没有初始化)
2>初始化 (对象方法:-(id)init,返回初始化好的对象)
new就是包含了alloc和init两个方法。
init就是构造方法。
重写init方法分三步:
1>调用父类init方法,且赋值给self,初始化父类中声明的一些成员变量和其他属性。
2>判断self是否为空。不为空才算初始化成功,才有必要进行自定义的初始化内容。
3>返回self。
#import <Foundation/Foundation.h>@interface Person : NSObject//自动生成相应的set和get方法声明,同时也实现了这些方法@property int age;@property NSString * name;@end@implementation Person//重写init方法- (id)init{ if(self=[super init]) { _age=23; NSLog(@"Person 初始化完毕,age=%d",_age); } return self;}@endint main(){ Person *p=[[Person alloc]init]; p=[Person new]; // 可见直接调用new是一样的,因为new本来就是包含了alloc和init return 0;}
//程序结果://2014-12-12 19:18:31.558 核心语法[1137:303] Person 初始化完毕,age=23//2014-12-12 19:18:31.561 核心语法[1137:303] Person 初始化完毕,age=23
自定义构造方法
规范:1>一定是对象方法,一定是以-开头
2>返回值一般是id类型
3>方法名一般以initWith开头
#import <Foundation/Foundation.h>//Persdon类@interface Person : NSObject//自动生成_age和_name,且自动生成他们的set和get方法声明及实现@property int age;@property NSString *name;//自定义构造方法- (id)initWithAge:(int)age andName:(NSString *)name;@end@implementation Person//自定义构造方法的实现- (id)initWithAge:(int)age andName:(NSString *)name{ if(self=[super init]) { _age=age; _name=name; } return self;}@end//Student类@interface Student : Person@property int number;//自定义构造方法- (id)initWithAge:(int)age andName:(NSString *)name andNumber:(int)number;@end@implementation Student//实现自定义构造方法- (id)initWithAge:(int)age andName:(NSString *)name andNumber:(int)number{ //父类内部的成员变量,尽量用父类自己的方法访问 if(self=[super initWithAge:age andName:name]) { _number=number; } return self;}@endint main(){ //用自定义的构造方法初始化对象 Person *p=[[Person alloc] initWithAge:23 andName:@"LIMING"]; NSLog(@"age--%d,name--%@",p.age,p.name); Student *s=[[Student alloc]initWithAge:34 andName:@"haha" andNumber:1234]; NSLog(@"age=%d,name=%@,number=%d",s.age,s.name,s.number); return 0;}
六、分类(category)
可以给某个类扩充一些方法,在不修改原来类的代码的情况下。
格式:
//分类声明@interface 类名(分类名称)@end//分类实现@implementation 类名(分类名称)@end
注意:
1.分类只能加方法,不能加成员变量。
2.分类方法实现中可以访问原来类中声明的成员变量。
3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用。
4.方法调用的优先级:分类(最后参与编译的分类优先)>原来类>父类
(Xcode中调整.m文件编译顺序:点击项目名称->Build Phases->Compile Sources,在这里上下拖动可以调换顺序)
#import <Foundation/Foundation.h>//NSString类的分类@interface NSString (numCount)//声明方法计算字符串中数字的个数,一个类方法,一个对象方法+ (int)countOfString:(NSString *)str;- (int)count;@end@implementation NSString (numCount)+ (int)countOfString:(NSString *)str{ int count=0; for(int i=0;i<[str length];i++) { //判断每个位置上德字符是不是在0-9之间 if([str characterAtIndex:i]>='0'&&[str characterAtIndex:i]<='9') count++; } return count;}- (int)count{ //直接调用类方法 return [NSString countOfString:self];}@end//Persdon类@interface Person : NSObject//自动生成_age和_name,且自动生成他们的set和get方法声明及实现@property int age;@property NSString *name;@end//preson类的实现@implementation Person@end//Person的分类@interface Person (Beijing)- (void)test;@end@implementation Person (Beijing)- (void)test{ NSLog(@"%@",@"beijing");}@end//Person的分类@interface Person (Nanjing)- (void)test;@end@implementation Person (Nanjing)- (void)test{ NSLog(@"%@",@"nanjing");}@endint main(){ Person *p=[[Person alloc] init]; [p test];//调整Person两个分类的编译顺序时,结果是不同的 NSLog(@"%d",[NSString countOfString:@"123"]);//调用自定义的类方法 NSLog(@"%d",[@"s1d" count]); // 调用自定义的对象方法 return 0;}八、 类的本质
1. 类也是个对象
其实类也是一个对象,是Class类型的对象,简称“类对象”。
类名就代表着类对象,每个类只有一个类对象。
Class类型的定义:typedef struct objc_class *Class;(也就是本质是指针)
2. +load和+initialize
+load
在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法
先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load
先加载元原始类,再加载分类
不管程序运行过程有没有用到这个类,都会调用+load加载
+initialize
在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法
一个类只会调用一次+initialize方法,先调用父类的,再调用子类的(要是分类重写了initialize方法,就直接调用分类的,原始类就不调用了)
3. 获取类对象的2种方式
Class c = [Person class]; // 类方法
或者
Person *p = [Person new];
Class c2 = [p class]; // 对象方法
4. 类对象调用类方法
Class c = [Person class];
Person *p2 = [c new];
#import <Foundation/Foundation.h>//Persdon类@interface Person : NSObject+ (void)test;@end//preson类的实现@implementation Person+ (void)test{ NSLog(@"Person的类方法-test");}+(void)load{ NSLog(@"Person----------load");}+ (void)initialize{ NSLog(@"Person-----initialize");}@end//Person的分类@interface Person (Beijing)@end@implementation Person (Beijing)+(void)load{ NSLog(@"Person (Beijing)----------load");}+ (void)initialize{ NSLog(@"Person (Beijing)-----initialize");}@end//Student类@interface Student : Person@end@implementation Student+(void)load{ NSLog(@"Student----------load");}+ (void)initialize{ NSLog(@"Student-----initialize");}@endint main(){ Person *p=[[Person alloc] init]; Class c=[Person class]; // 通过类方法获取Person的类对象 Class c1=[p class]; // 通过对象方法获取Person的类对象 NSLog(@"%p---%p",c,c1); //地址相同,即二者都是指向Person类对象,这个类对象只有一个 //类对象调用类方法 [c test]; Person *p1=[c new]; return 0;}//执行结果://2014-12-13 00:04:37.832 核心语法[2141:303] Person----------load//2014-12-13 00:04:37.834 核心语法[2141:303] Student----------load//2014-12-13 00:04:37.835 核心语法[2141:303] Person (Beijing)----------load//2014-12-13 00:04:37.836 核心语法[2141:303] Person (Beijing)-----initialize//2014-12-13 00:04:37.837 核心语法[2141:303] 0x1000012c0---0x1000012c0//2014-12-13 00:04:37.837 核心语法[2141:303] Person的类方法-test
九、descrition方法
1. -description方法
使用NSLog和%@输出某个对象时(默认输出的是“类名+内存地址”),会调用对象的-description方法,并拿到返回值进行输出
2. + description方法
使用NSLog和%@输出某个类对象时(默认输出类名),会调用类对象+description方法,并拿到返回值进行输出
3. 死循环陷阱
如果在-description方法中使用NSLog打印self
注意:NSLog输出C语言字符串时,字符串内不能含有中文
#import <Foundation/Foundation.h>//Persdon类@interface Person : NSObject@property int age;@property NSString *name;@end//preson类的实现@implementation Person//重写类方法+ (NSString *)description{ return @"=======";}//重写对象方法- (NSString *)description{ return [NSString stringWithFormat:@"Persion-age=%d,name=%@",self.age,self.name];}@endint main(){ Person *p=[[Person alloc] init]; p.age=12; p.name=@"xiaoming"; NSLog(@"%@",p); // 会调用对象的description方法 Class c=[Person class]; NSLog(@"%@",c); //会调用类的description方法 return 0;}//运行结果://2014-12-13 01:05:00.812 核心语法[2397:303] Persion-age=12,name=xiaoming//2014-12-13 01:05:00.815 核心语法[2397:303] =======
十、SEL
1. 方法的存储位置
每个类的方法列表都存储在类对象中每个方法都有一个与之对应的SEL类型的对象
根据一个SEL对象就可以找到方法的地址,进而调用方法
SEL类型的定义:typedef struct objc_selector *SEL;
#import <Foundation/Foundation.h>//Persdon类@interface Person : NSObject- (void)test;- (void)test1:(NSString *)name;- (void)name:(int)num;@end//preson类的实现@implementation Person- (void)test{ NSLog(@"---------");}- (void)test1:(NSString *)name{ NSLog(@"name=%@",name);}/* 每个方法都有一个隐藏的SEL数据类型:_cmd,这个数据代表方法本身 同样的,知道一个方法的SEL类型,也可以变成字符串 */- (void)name:(int)num{ NSString *name1=NSStringFromSelector(_cmd); NSLog(@"%@--%d",name1,num);}@endint main(){ Person *p=[[Person alloc] init]; [p test];//直接调用对象方法test [p performSelector:@selector(test)]; // 间接调用 /* 直接调用对象方法的过程: 1.把该方法包装成SEL类型的数据 2.根据SEL数据找到对应的方法地址 3.根据方法地址调用对应的方法 */ //创建SEL对象 SEL s=@selector(test1:); //间接调用带参数的方法 [p performSelector:s withObject:@"lixiao"]; //假如知道一个方法名得字符串形式,也可以转换为SEL NSString *name=@"test1:"; SEL s1=NSSelectorFromString(name);// 调用了一个函数,将字符串转换为SEL [p performSelector:s1 withObject:@"hah"]; [p name:23];//打印函数名称 return 0;}SEL其实是对方法的一种包装,将方法包装成SEL类型的数据,去找对应方法的地址,找到方法地址就可以调用该方法。消息机制的消息就是SEL
- OC核心语法
- OC核心语法
- OC核心语法
- ⑦--OC核心语法
- OC-8-核心语法
- OC语言核心语法
- OC 核心语法
- OC 核心语法罗列
- OC语法的核心
- OC核心语法(二)
- OC学习之核心语法
- OC语言之核心语法
- 黑马程序员----OC核心语法
- 学习笔记:OC核心语法
- OC学习之核心语法
- OC核心语法之分类
- OC-面对对象的核心语法
- 黑马程序员-10.OC的核心语法
- Java的native方法
- OUYA——下载并运行游戏Demo(开发环境配置5)
- [leetcode]Intersection of Two Linked Lists —— 熟悉python
- AFNetworking的学习
- IOS GCD学习之 —— 基本概念 & Dispatch Queue & dispatch_once
- OC核心语法
- 删除目录以及目录下面的子目录、文件
- BestWiring——Kruskal算法&并查集
- SSDB与Redis的区别
- java Spring常用工具类
- PHP无限分类代码 做好事不留名 就是这么任性
- 理解随机森林
- IOS 计算沙盒中一个目录的大小
- C++析构函数