002-OC基础语法

一、关键字:improt与include

1.相同点

  improt与include都有文件包含的功能

2.不同点

  improt是OC的关键字,而include是C的关键字;二者的最大区别在于improt可以防止重复包含,而include则容易造成重复包含的问题。

 

二、关键字:NSLog与printf

NSLog是OC的关键字,printf是C的关键字;前者打印输出自动换行,并且打印输出会有时间、日期等信息

 

三、OC的数据类型

1.OC的数据类型分类

  1)基本数据类型:int、float、double、char

  2)对象类型:OC的对象类型实际就是C的结构体

  3)id类型:泛型指针

  4)BOOL类型:本质就是char类型,可以当成整数来用(YES = 1, NO = 0)

  5)SEL类型:方法包装

  6)block类型:本质就是指向函数的指针,另外block弥补了指向函数的指针不能直接保存一个函数体

2.数据类型的特征

  1)可作为参数传递

  2)可作为函数的返回值

  3)可以声明成变量

3.数据类型的作用

  OC中的这些数据类型也是为了更加合理地分配内存空间

4.重点讲解

  1)SEL类型

    我们声明对象的方法,被包装成一个SEL类型的变量(SEL s = @selector(方法名))放在对象方法列表中,我们在调用对象方法时,实际上是对象里的isa指针指向该方法列表中SEL变量,通过这个变量指针地址去查找相应的方法。

 1 // Person.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface Person : NSObject
 5 
 6 #pragma mark - 成员属性
 7 @property (nonatomic, copy) NSString *name;
 8 @property (nonatomic, assign) int age;
 9 @property (nonatomic, copy) NSString *sex;
10 
11 #pragma mark - 方法
12 - (void)name:(NSString *)name age:(int)age sex:(NSString *)sex;
13 
14 @end
15 
16 
17 // Person.m文件
18 #import "Person.h"
19 
20 @implementation Person
21 
22 #pragma mark - 方法
23 - (void)name:(NSString *)name age:(int)age sex:(NSString *)sex
24 {
25     NSLog(@"name = %@, age = %d, sex = %@", name, age, sex);
26 }
27 
28 @end
29 
30 
31 // ViewController.m文件
32 #import "ViewController.h"
33 #import "Person.h"
34 
35 @implementation ViewController
36 
37 - (void)viewDidLoad {
38     [super viewDidLoad];
39  
40     Person *p = [[Person alloc] init];
41     p.name = @"Frank";
42     p.age = 25;
43     p.sex = @"M";
44     // 将方法包装成SEL类型
45     // SEL abc = @selector(name:age:sex:);
46     // 通过performSelector:方法调用SEL类型的对象方法
47     [p performSelector:@selector(name:age:sex:)];
48 }
49 
50 @end

  2)block类型

    实例一:block作为函数参数传递

 1 // Calculate.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 #pragma mark - block类型的声明
 5 typedef int(^CalculateBlock)(int a, int b);
 6 
 7 @interface Calculate : NSObject
 8 
 9 #pragma mark - 将block类型作为函数参数传递
10 - (int)calculateWithNumber1:(int)num1 number2:(int)num2 calculateBlock:(CalculateBlock)calculate;
11 
12 @end
13 
14 
15 // Calculate.m文件
16 #import "Calculate.h"
17 
18 @implementation Calculate
19 
20 #pragma mark - block作为函数参数传递,其调用在函数调用的时候进行
21 - (int)calculateWithNumber1:(int)num1 number2:(int)num2 calculateBlock:(CalculateBlock)calculate
22 {
23     return calculate(num1, num2);
24 }
25 
26 @end
27 
28 
29 // ViewController.m文件
30 #import "ViewController.h"
31 #import "Calculate.h"
32 
33 @implementation ViewController
34 
35 - (void)viewDidLoad {
36     [super viewDidLoad];
37     
38     Calculate *cal = [[Calculate alloc] init];
39     int sum = [cal calculateWithNumber1:20 number2:30 calculateBlock:^int(int a, int b) {
40         return a + b;
41     }];
42     NSLog(@"sum = %d", sum);
43 }
44 
45 @end

    实例二:block作为成员变量

 1 // Calculate.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 #pragma mark - block类型的声明
 5 typedef int(^CalculateBlock)(int a, int b);
 6 
 7 @interface Calculate : NSObject
 8 
 9 #pragma mark - 将block类型作为成员属性
10 @property (nonatomic, copy) CalculateBlock cb;
11 
12 #pragma mark - 方法
13 - (void)calculateWithNum1:(int)num1 num2:(int)num2;
14 
15 @end
16 
17 
18 // Calculate.m文件
19 #import "Calculate.h"
20 
21 @implementation Calculate
22 
23 #pragma mark - 方法实现
24 - (void)calculateWithNum1:(int)num1 num2:(int)num2
25 {
26     // 判断block作为成员变量,是否被赋值
27     if (self.cb) {
28         // 如果被赋值,就被调用
29         self.cb(num1, num2);
30     }
31 }
32 
33 @end
34 
35 
36 // ViewController.m文件
37 #import "ViewController.h"
38 #import "Calculate.h"
39 
40 @implementation ViewController
41 
42 - (void)viewDidLoad {
43     [super viewDidLoad];
44     
45     Calculate *cal = [[Calculate alloc] init];
46     // 给cal对象的block类型成员变量cb赋值 -- 也就是block的实现
47     cal.cb = ^ int (int a, int b) {
48         int sum = a + b;
49         return sum;
50     };
51     
52     // 调用cal方法
53     [cal calculateWithNum1:20 num2:30];
54 }
55 
56 @end

    实例三:主动调用block,block修改外部变量的值

 1 // ViewController.m文件
 2 #import "ViewController.h"
 3 
 4 #pragma mark - block类型的声明
 5 typedef void(^BoolBlock)(BOOL);
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11     
12     // block内部想要改变外部变量的值,则必须使用__block修饰该变量
13     __block int i = 1024;
14     BoolBlock cb = ^(BOOL bv) {
15         if (bv) {
16             // block内部修改外部变量的值
17             i++;
18         }
19     };
20     BOOL a = YES;
21     
22     // 主动调用一下block
23     cb(a);
24 }
25 
26 @end

    关于block,需要注意一下几点:

      a.block做成员变量,参数必须用copy,copy会将block的生命周期从栈转移到堆空间,其生命周期就会交给程序员自己管理,不会出现block被提前释放,也就不会造成block野指针错误

      b.block作为参数时,为防止循环引用,必须放在函数尾部

      c.默认情况下,任何的block都是放在栈里边,随时都可能会被回收,block没有使用retain,理由是retain只是计数器加1,内存地址不会改变,因而不能将block从栈里边放到堆里

      d.MRC模式下用__block去修饰block代码块内部需要引用的对象,在ARC模式下用__weak去修饰block内部引用的对象,这样可防止由于循环引用造成的内存泄露

      e.block内部修改外部变量的值,必须使用__block修饰该变量,一般情况下我们不建议在block内部去修改外部变量的值

 

四、Category(类别、分类)

1.Category的基本要点

  1)分类只是扩展方法,不可以扩展成员变量;但是在分类中是可以直接访问原来类中.h文件声明的所有方法和所有成员变量

  2)分类可以在不获悉、不改变原来类的的同时,可以为原来类扩展一些方法;但是分类只可以扩展原来类的方法,不可以修改和删除原来类的方法

  3)在分类中重写原类中的方法,会覆盖原来类的方法,并且该重写后的方法只会在分类中有效,对于原来的类是没有影响

  4)在同一个原有类的多个分类中如果出现了相同的方法,系统会根据编译顺序来决定调用的是哪一个分类中的扩展方法

  5)分类是可以被继承的,在父类中导入分类的头文件,那么在其子类中也是可以访问分类中的扩展方法

2.Category的优点

  1)将类的实现分散到多个不同的文件或是不同的框架中

  2)可以向对象添加非正式协议

  3)创建私有方法的前向引用

3.Category的创建步骤

  

  

  

 1 // NSString+LD.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface NSString (LD)
 5 
 6 #pragma mark - 统计字符串中0-9的个数
 7 + (int)numberCountOfString:(NSString *)string;
 8 #pragma mark - 统计字符串中0-9的个数
 9 - (int)numberCount;
10 
11 @end
12 
13 
14 // NSString+LD.m文件
15 #import "NSString+LD.h"
16 
17 @implementation NSString (LD)
18 
19 #pragma mark - 统计字符串中0-9的个数
20 + (int)numberCountOfString:(NSString *)string
21 {
22     return [string numberCount];
23 }
24 
25 #pragma mark - 统计字符串中0-9的个数
26 - (int)numberCount
27 {
28     int count = 0;
29     for (int i = 0; i < self.length; i++) {
30         unichar c = [self characterAtIndex:i];
31         // 字符都是以ASCII码存储的
32         if (c >= '0' && c <= '9') {
33             count++;
34         }
35     }
36     return count;
37 }
38 
39 @end
40 
41 
42 // ViewController.m文件
43 #import "ViewController.h"
44 #import "NSString+LD.h"    // 导入分类头文件
45 
46 @implementation ViewController
47 
48 - (void)viewDidLoad {
49     [super viewDidLoad];
50     
51     // 调分类中的类方法
52     int num1 = [NSString numberCountOfString:@"34ty6iui2"];
53     NSLog(@"num1 = %d", num1);
54     
55     // 调用分类中的对象方法
56     NSString *string = @"34ty6iui2";
57     int num2 = [string numberCount];
58     NSLog(@"num2 = %d", num2);
59 }
60 
61 @end

4.补充说明

  分类中不可以扩展原来类的成员变量也不是绝对的。比如在分类中引进运行(runtime),是可以扩展成员属性的。因为分类扩展的成员变量是不能生成get和set方法的,那么我们可以在.m文件中引进运行时技术,动态地给成员变量添加两个方法(get和set方法)

 1 // Person.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface Person : NSObject
 5 
 6 @property (nonatomic, copy) NSString *name;
 7 @property (nonatomic, assign) int age;
 8 
 9 @end
10 
11 
12 // Person.m文件
13 #import "Person.h"
14 
15 @implementation Person
16 
17 @end
18 
19 
20 // Person+LD.h文件
21 #import "Person.h"
22 
23 @interface Person (LD)
24 
25 #pragma mark - 分类中扩展的成员属性
26 @property (nonatomic, assign) double height;
27 
28 @end
29 
30 
31 // Person+LD.m文件
32 #import "Person+LD.h"
33 #import <objc/message.h>  // 导入运行时头文件
34 
35 @implementation Person (LD)
36 
37 // 静态变量
38 static double HeightKey;
39 
40 #pragma mark - set方法
41 - (void)setHeight:(double)height
42 {
43     objc_setAssociatedObject(self, &HeightKey, @(height), OBJC_ASSOCIATION_ASSIGN);
44 }
45 
46 #pragma mark - get方法
47 - (double)height
48 {
49     return [objc_getAssociatedObject(self, &HeightKey) doubleValue];
50 }
51 
52 @end
53 
54 
55 // ViewController.m文件
56 #import "ViewController.h"
57 #import "Person+LD.h"  // 导入分类头文件
58 
59 @implementation ViewController
60 
61 - (void)viewDidLoad {
62     [super viewDidLoad];
63     
64     // 调用
65     Person *p = [[Person alloc] init];
66     p.name = @"Frank";
67     p.age = 25;
68     p.height = 110.5;     // 分类中扩展的成员属性
69     NSLog(@"height = %.2f", p.height);
70 }
71 
72 @end

 5.总结

  分类是对一些系统的类进行功能的补充。就好比是一个产品当你发现它的缺陷和一些不足时,你就会想着去完善和补充,但是产品的缘由功能都是存在的

 

五、Protocol(协议)

1.Protocol的基本要点

  1)协议方法的声明部分在协议文件中

  2)协议方法的实现部分在遵循该协议的类文件中

  3)协议中被关键字@required修饰的协议方法必须在遵循该协议类中去实现,协议中被关键字@optional修饰的协议方法可以选择实现

  4)对于必须实现的协议方法,我们在调用的时候可以随意调用;但是对于可选择实现的协议方法,我们必须先确定已被实现,方可调用,否则会造成程序异常

  5)所有的协议都是遵循基协议NSObject

  6)父类遵循的协议,同样会被继承父类的子类所遵循;但是子类如果不自己实现该协议方法,那么利用该子类调用该协议方法时,其本质还是相当于父类在调用

  7)协议中是不可以声明成员变量的

  8)判断遵循协议类是否实现某个协议方法:performSelector:@selector(协议方法)

2.Protocol的创建步骤

  

  

 

  

3.在实际开发中的情况

  实例一:单独创建一个协议文件

 1 // LDFrankDelegate.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @protocol LDFrankDelegate <NSObject>
 5 
 6 #pragma mark - 协议方法的声明部分
 7 // 必须实现的协议方法(霸王条款)
 8 @required
 9 - (void)eat;
10 - (void)drink;
11 
12 // 可以选择实现的方法
13 @optional
14 - (void)gamble;
15 - (void)walk;
16 
17 @end
18 
19 
20 // Person.h文件
21 #import <Foundation/Foundation.h>
22 #import "LDFrankDelegate.h"  // 导入协议文件
23 
24 @interface Person : NSObject<LDFrankDelegate> // 遵循协议
25 
26 @end
27 
28 
29 // Person.m文件
30 #import "Person.h"
31 
32 @implementation Person
33 
34 #pragma mark - 协议方法的实现部分
35 // 必须实现以下协议方法
36 - (void)eat
37 {
38     NSLog(@"eat");
39 }
40 - (void)drink
41 {
42     NSLog(@"drink");
43 }
44 
45 // 可以选择实现以下协议方法
46 - (void)gamble
47 {
48     NSLog(@"gamble");
49 }
50 
51 @end
52 
53 
54 // ViewController.m文件
55 #import "ViewController.h"
56 #import "Person.h"
57 
58 @implementation ViewController
59 
60 - (void)viewDidLoad {
61     [super viewDidLoad];
62     
63     Person *p = [[Person alloc] init];
64     // 必须实现的协议方法调用
65     [p eat];
66     [p drink];
67     
68     // 可实现的协议方法调用
69     // 必须先判断该协议方法是否被实现
70     if ([p performSelector:@selector(gamble)]) {
71         [p gamble];
72     }
73     if ([p performSelector:@selector(walk)]) {
74         [p walk];
75     }
76 }
77 
78 @end

   实例二:直接将协议文件写入遵循该协议文件中

 1 // Person.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 #pragma mark - 协议的声明
 5 @protocol LDFrankDelegate <NSObject>
 6 
 7 #pragma mark - 协议方法的声明部分
 8 // 必须实现的协议方法(霸王条款)
 9 @required
10 - (void)eat;
11 - (void)drink;
12 
13 // 可以选择实现的方法
14 @optional
15 - (void)gamble;
16 - (void)walk;
17 
18 @end
19 
20 @interface Person : NSObject<LDFrankDelegate> // 遵循协议
21 
22 @end
23 
24 
25 // Person.m文件
26 #import "Person.h"
27 
28 @implementation Person
29 
30 #pragma mark - 协议方法的实现部分
31 // 必须实现以下协议方法
32 - (void)eat
33 {
34     NSLog(@"eat");
35 }
36 - (void)drink
37 {
38     NSLog(@"drink");
39 }
40 
41 // 可以选择实现以下协议方法
42 - (void)gamble
43 {
44     NSLog(@"gamble");
45 }
46 
47 @end

4.总结

  Protocol只是定义一些接口,是定义行为而不管谁去实现,是一种不负责任行为。就好比在产品外包中,外发公司只需要拿到功能完善的产品,而不去理睬功能实现的过程。

 

六、继承

1.成员变量的访问属性

  1)private:私有成员属性,不能被外部函数访问,也不能被子类所继承

  2)protected:保护成员属性,不能被外部函数访问 ,但是可被子类继承

  3)public:公有成员属性,可以被外部函数访问,也可以被子类继承

  4)OC中,所有的方法都是公有的

2.关于继承的几个要点

  1)OC中的NSObject是大部分类的父类,我们称之为基类或是根类,只有当继承自NSObject这个基类,才有创建对象的能力

  2)子类可从父类继承方法,但有时父类的方法不适合子类,子类就可写一个自己的同名方法,覆盖掉父类的同名方法,叫做重写。重写时,在子类的.h中不必重新声明,直接在.m中写实现即可

  3)子类可以创建自己的独有方法,该独有方法必须在子类中有完整的声明和实现;子类同时也可以创建自己的成员属性。子类在原有继承基础上,创建自己独有的成员属性和方法,叫做派生

  4)父类指针可以指向子类

3.继承的好处

  1)创建大量的相似类的时候,可以先创建一个父类,父类中写一些公有的特性,使这些相似的类继承父类,可以节省工作量

  2)使用框架中的类,或是已经写好的类,继承该类,生成一个派生类,比原类更好用(NSString、NSArray、NSDictionary都是不能够被继承的)

4.继承的创建步骤

  

  

5.实际开发中的问题

  1 // Person.h文件
  2 #import <Foundation/Foundation.h>
  3 
  4 @interface Person : NSObject
  5 {
  6     // 公有的
  7     @public
  8         NSString *_name;
  9     
 10     // 受保护的
 11     @protected
 12         NSInteger _age;
 13     
 14     // 私有的
 15     @private
 16         NSInteger _money;
 17 }
 18 
 19 @property (nonatomic, copy) NSString *name;
 20 @property (nonatomic, assign) NSInteger age;
 21 @property (nonatomic, assign) NSInteger money;
 22 
 23 #pragma mark - 父类的方法的声明
 24 - (void)eat;
 25 - (void)drink;
 26 
 27 @end
 28 
 29 
 30 // Person.m文件
 31 #import "Person.h"
 32 
 33 @implementation Person
 34 
 35 #pragma mark - 父类的方法的实现
 36 - (void)eat
 37 {
 38     NSLog(@"Person eat");
 39 }
 40 - (void)drink
 41 {
 42     NSLog(@"Person drink");
 43 }
 44 
 45 @end
 46 
 47 
 48 // Boy.h文件
 49 #import "Person.h"
 50 
 51 @interface Boy : Person
 52 
 53 #pragma mark - 子类独有的成员属性(派生)
 54 @property (nonatomic, copy) NSString *habit;
 55 
 56 #pragma mark - 子类独有的方法的声明(派生)
 57 - (void)test;
 58 
 59 @end
 60 
 61 
 62 // Boy.m文件
 63 #import "Boy.h"
 64 
 65 @implementation Boy
 66 
 67 #pragma mark - 子类独有方法的实现
 68 - (void)test
 69 {
 70     // 父类中public和protected修饰的成员属性在子类中可以直接访问
 71     _name = @"Frank";
 72     _age = 25;
 73     
 74     // 父类中private修饰的成员属性在子类中不可以直接访问,只能通过父类的方法去访问
 75     // _money = 50000000;    // 这个就会报错
 76     self.money = 50000000;
 77     [self setMoney:50000000];
 78     
 79     NSLog(@"name = %@, age = %ld, money = %ld", _name, _age, [self money]);
 80 }
 81 
 82 #pragma mark - 子类重写父类的方法
 83 - (void)eat
 84 {
 85     NSLog(@"男孩都喜欢吃好吃的");
 86 }
 87 
 88 @end
 89 
 90 
 91 // ViewController.m文件
 92 #import "ViewController.h"
 93 #import "Boy.h"    // 导入子类的头文件
 94 
 95 @implementation ViewController
 96 
 97 - (void)viewDidLoad {
 98     [super viewDidLoad];
 99 
100     // 父类的指针可以指向子类
101     Person *p = [[Boy alloc] init];
102     
103     // 父类指针指向子类,调用的方法如果是子类的重写方法,那么其调用的还是子类的方法
104     [p eat];
105     
106     // 父类指针指向子类,不可以通过父类指针调用子类的派生方法
107     // [p test];    // 这个会报错
108 }
109 
110 @end

 

七、多态

1.概念

  对态就是给不同的对象发送相同的消息,得到的反应结果是不一样的

2.实现多态的条件

  1)必须有继承关系:实现多态的对象必须是满足继承关系的对象

  2)必须有重写父类的方法

  3)必须有父类指针指向子类的对象

3.多态在实际开发中的应用

  总结:响应消息,不看指针,看对象

  1 // Animal.h文件
  2 #import <Foundation/Foundation.h>
  3 
  4 @interface Animal : NSObject
  5 
  6 #pragma mark - 父类方法的声明
  7 - (void)beated;
  8 
  9 @end
 10 
 11 
 12 // Animal.m文件
 13 #import "Animal.h"
 14 
 15 @implementation Animal
 16 
 17 #pragma mark - 父类方法的实现
 18 - (void)beated
 19 {
 20     NSLog(@"父类被打, 不知道怎么反应!");
 21 }
 22 
 23 @end
 24 
 25 
 26 // Cat.h文件
 27 #import "Animal.h"
 28 
 29 @interface Cat : Animal
 30 
 31 @end
 32 
 33 
 34 // Cat.m文件
 35 #import "Cat.h"
 36 
 37 @implementation Cat
 38 
 39 #pragma mark - 重写父类方法
 40 - (void)beated
 41 {
 42     NSLog(@"猫被打:miao, miao, 跑到树上!");
 43 }
 44 
 45 @end
 46 
 47 
 48 // Tiger.h文件
 49 #import "Animal.h"
 50 
 51 @interface Tiger : Animal
 52 
 53 @end
 54 
 55 
 56 // Tiger.m文件
 57 #import "Tiger.h"
 58 
 59 @implementation Tiger
 60 
 61 #pragma mark - 重写父类方法
 62 - (void)beated
 63 {
 64     NSLog(@"老虎被打:Come on, I am hungry!");
 65 }
 66 
 67 @end
 68 
 69 
 70 // Wolf.h文件
 71 #import "Animal.h"
 72 
 73 @interface Wolf : Animal
 74 
 75 @end
 76 
 77 
 78 // Wolf.m文件
 79 #import "Wolf.h"
 80 
 81 @implementation Wolf
 82 
 83 #pragma mark - 重写父类方法
 84 - (void)beated
 85 {
 86     NSLog(@"狼被打: 我还会回来的!");
 87 }
 88 
 89 @end
 90 
 91 
 92 // Person.h文件
 93 #import <Foundation/Foundation.h>
 94 #import "Animal.h"
 95 
 96 @interface Person : NSObject
 97 
 98 #pragma mark - Animal 可以接受所有的子类
 99 // 参数:animal,可以接受所有继承自Animal类的子类对象
100 - (void)beat:(Animal *)animal;
101 
102 @end
103 
104 
105 // Person.m文件
106 #import "Person.h"
107 
108 @implementation Person
109 
110 #pragma mark - 使用了父类的指针,作为形参
111 - (void)beat:(Animal *)animal
112 {
113     NSLog(@"%@ 被打啦", NSStringFromClass([animal class]));
114     [animal beated];
115 }
116 
117 @end
118 
119 
120 // ViewController.m文件
121 #import "ViewController.h"
122 #import "Person.h"
123 #import "Cat.h"
124 #import "Tiger.h"
125 #import "Wolf.h"
126 
127 @implementation ViewController
128 
129 - (void)viewDidLoad {
130     [super viewDidLoad];
131 
132     
133     Person *p = [[Person alloc] init];
134     
135     // 初始化子类
136     Cat *cat = [[Cat alloc] init];
137     Tiger *tiger = [[Tiger alloc] init];
138     Wolf *wolf = [[Wolf alloc] init];
139     
140     // 通过父类指针调用子类重写的方法 -- 得到不同的反应结果
141     [p beat:cat];
142     [p beat:tiger];
143     [p beat:wolf];
144 }
145 
146 @end

 

八、封装

1.类是对数据和功能的封装。其中成员属性就是读对数据的封装,而方法就是对功能的封装

2.在OC语言中,使用@interface和@implementation来处理类

3.@interface就好像暴露在外面的时钟表面,像外界提供展示以及接口。

4.@implementation就好像隐藏在时钟内部的构造实现,把具体的实现封装了起来。

 

九、self关键字与点语法

1.self关键字

  1)self是一个指针,谁调用了当前方法,self就指向谁(出现在对象方法中,就代表着当前对象,出现在类方法中,就代表着当前类)

  2)self的用途:

    a.可以利用 self->成员变量名 访问当前对象内部的成员变量(仅在对象方法中)

    b.[self 方法名];可以调用其他的对象方法或者是类方法

 2.点语法

  1)为什么要使用点语法

    a.为了方便别的程序员转到OC上面来(C++/Java/C#都是使用的点语法)

    b.为了让程序设计简单化,隐藏一些内存管理、多线程、同步、枷锁的细节

  2)点语法的调用

    a.点语法与set方法:

      person.name = @"Frank";       // 点语法赋值

      [person setName:@"Frank"];   // set方法

    b.点语法与get方法:

      person.name;                        // 点语法取值

      [person name];                     // get方法

  3)点语法的条件

    a.对象调用点语法,对象必须实现set和get方法

    b.使用点语法的set方法,只能够带有一个参数

 

十、对象之间的关系

1.匿名对象

 1 // Book.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface Book : NSObject
 5 
 6 @end
 7 
 8 
 9 // Book.m文件
10 #import "Book.h"
11 
12 @implementation Book
13 
14 @end
15 
16 
17 // Person.h文件
18 #import <Foundation/Foundation.h>
19 #import "Book.h"
20 
21 @interface Person : NSObject
22 
23 #pragma mark - 成员属性
24 @property (nonatomic, copy) NSString *name;
25 
26 #pragma mark - 方法声明
27 - (void)readBook:(Book *)book;
28 
29 @end
30 
31 
32 // Person.m文件
33 #import "Person.h"
34 
35 @implementation Person
36 
37 #pragma mark - 方法实现
38 - (void)readBook:(Book *)book
39 {
40     NSLog(@"读书");
41 }
42 
43 @end
44 
45 
46 // ViewController.m文件
47 #import "ViewController.h"
48 #import "Person.h"
49 #import "Book.h"
50 
51 @implementation ViewController
52 
53 - (void)viewDidLoad {
54     [super viewDidLoad];
55  
56     // [类名 new];   // 创建一个匿名对象
57     [[Person new] readBook:[Book new]];
58 }
59 
60 @end

  匿名对象的作用:

    1)当调用使用次数很少的方法的时候,就直接使用匿名对象调用

    2)匿名对象可以作为参数传递,当不需要给传递的对象的成员变量赋值的时候,就使用匿名对象作为参数传递

2.依赖关系

  1)A对象作为B对象的局部变量或是方法形参,则B依赖于A,这时我们讲AB对象之间是一种依赖关系

  2)在面向对象编程中:

    耦合度:指的是修改一个对象而对另一个对象的影响程度

    低耦合:指的是修改一个对象对其他对象的影响程度比较小

    高内聚:一个对象仅仅只做与自己相关的事情

3.关联关系

  简单地讲,就是指A对象为B对象的成员变量,我们就说A对象与B对象之间存在一种关联关系

  关联关系的耦合度要高于依赖关系

 

十一、类与对象

1.类

  1)类的本质:类其实也是个对象,只不过是类对象

 1 // Person.h文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface Person : NSObject
 5 
 6 #pragma mark - 成员属性
 7 @property (nonatomic, copy) NSString *name;
 8 @property (nonatomic, assign) NSInteger age;
 9 
10 @end
11 
12 
13 // Person.m文件
14 #import "Person.h"
15 
16 @implementation Person
17 
18 @end
19 
20 
21 // Viewcontroller.m文件
22 #import "ViewController.h"
23 #import "Person.h"  // 导入头文件
24 
25 @implementation ViewController
26 
27 - (void)viewDidLoad {
28     [super viewDidLoad];
29     
30     // 1.利用类去创建类的对象
31     Person *p = [[Person alloc] init];
32     p.name = @"Dave";
33     p.age = 10;
34     
35     // 2.利用类对象去创建类的对象
36     Class c = [p class];  // 内存中的类对象,我们也可以使用这个类对象去调用类方法
37     Person *p1 = [[c new] init];
38     p1.name = @"Frank";
39     p1.age = 25;
40 }
41 
42 @end

  2)类的加载

    两大方法:+ (void)load;  + (void)initialize;

      a.当程序启动时,就会加载项目中所有的类和分类,而且加载会调用load方法,该方法只会调用一次

      b.当程序第一次使用某个类时,就会调用该类的initialize方法

      c.类加载的顺序:先加载父类,再加载子类(先调用父类的load方法,后调用子类的load方法);对于分类,先加载原来类,再加载分类

      d.第一次使用子类:先初始化父类,再初始化子类(先调用父类的initialize方法,后调用子类的initialize方法)

2.对象

  OC的对象实质就是C语言中的结构体

 

十二、description方法

1.调用

  打印输出对象时调用该方法,我们一般可以在这里返回对象的属性输出

2.方法

  类方法:+ (NSString *)description;

  对象方法:- (NSString *)description;

 

 

(未完待续......)

posted @ 2015-12-16 21:08  Frank9098  阅读(166)  评论(0)    收藏  举报