面向对象的难易点:其实也就是封装:要会调封装,也要会自己封装,封装就是给出一些接口,让我们去用,我们不关心其实现,但往往学的时候不踏实
说他容易是用着容易,只要有接口,就可以完成很多我们想要的功能,但往往分不清功能是自己能实现还是通过别人写好的框架或者方法来帮我实现
所以需要记忆一些常用方法和框架.把自己的算法思想和一些接口框架相结合.
OC 有两种类型的方法,类方法和对象方法(也被称为实例方法)
1.类方法:以+开头,不分配内存空间(这句话,问题来了,为什么?)
什么时候分配内存空间,很显然只有创建对象的时候才会分配内存空间[self alloc]就是申请内存空间,申请的是对取得内存空间
而类方法是不会创建对象的,自然是不会被分配内存空间
那么:类方法是怎么调用方法的?
通过 [类名 类方法名称];去掉用,调用过程是直接跳过堆区,调用代码区的方法
也就是说类方法的调用是不经过堆区的,那么也就是说类方法不能访问存储在堆区中的成员变量(成员属性)
注意:无论是类方法还是对象方法在调用方法的时候,如果方法有返回值,那么调用方法的时候返回给调用者的都是一个返回值类型的对象(不要理解错误,认为类方法调用返回的是类,返回值和(类方法还是对象方法)无关,返回值要用对象接收)
2.匿名对象
匿名对象是没有名字的对象
匿名对象作用
1)可以访问实例变量
2)可以调用方法
3) 匿名对象在内存空间里面调用的时候,每调用一次就创建一块新的内存空间
3.封装:
首先什么是封装?
正解:此时我们说的封装就是只在interface文件中提供一个接口(set 或者get方法),把方法的实现放在implemention中,set和get方法其实就是把当前类的对象的成员属性
嵌入到set和get方法中,并且只能被当前类的对象访问(通俗讲就是我是一个对象,我有鼻子,眼睛等属性,我把鼻子眼睛封装起来,只能我自己用,别人让我吃东西,我可以给我嘴的属性加个判断,决定要不要吃,吃什么)
为什么要封装?
我就不封装会产生什么样的后果?我为啥不让别人访问我的数据,大家都用我的数据不好吗?
正解:这两个问题可以一起回答,苹果官方文档形象了解释了封装:如下图,
如果不封装:举两个小栗子:如果我写个Person类,类中声明一个age成员属性,如果不封装,任何人都可以访问我的成员属性,那么
别人如果给我的age一个负值(有人反驳说,为什么会有人这么傻逼给年龄赋值为负呢?那么我告诉你,因为我尼玛又没告诉你我写的属性age是年龄,
我不懂英语还可以写成egg,ega,我开心还写成dog呢,你管我,你知道我属性是干啥的,)如果别人把我定的年龄属性修改为负值了,那么带来的后果就是
我的产品上架,如果涉及到年龄的填写,那么客户写成负的值,也是可以通过的,这严重破坏用户体验,所以,我的属性是不能随便给人修改,如果我封装过这个属性
我自己是知道这个属性是干嘛的,我就可以在set方法中加一个属性判断,如果赋值为负,我可以提醒一下或者直接return,这样外界通过接口访问我的成员属性,
就不能随意修改,就可以解决问题
包括别的封装也是,我把一大段代码封装起来,只提供给你一个接口,那么你只需要知道你调用这个接口,我给你相应的数据即可,你不必知道我是怎么实现的,也
不可能让你知道,否则,我数据安全性就无法保证,就像苹果公司好多只提供一些接口,并给你一些注释信息告诉你,你调用我的接口,我的这个接口方法是用来干嘛干嘛的
,如果给你看了我如何实现这个功能的,那么你就掌握了我底层的算法,安全性从何而谈,估计苹果早就破产了.
所以,setter和getter只是对属性的一个简单封装而已,属于众多封装中的一种罢了
4.OC 中没有方法重载的概念
5.OC 中static关键字的理解:延伸:extern,const等关键字的使用?
首先static在C语言中能修饰什么?在OC 中能修饰什么?作用是干嘛的?怎么用?
正解:static在C语言中能
修饰局部变量:延长局部变量的生命周期
修饰全局变量:当前变量只能在当前文件中使用
修饰函数:函数值只能在当前文件中使用
static在OC语言中能
可以定义局部变量,但只能在.m文件中使用:作用就是延长局部变量的生命周期
强烈建议参考博客:http://www.jianshu.com/p/3fa703e80720
写的很全面
小结一下:
extern关键字:该关键字只能修饰全局变量
1.与.h文件的关系
.h的用法:想必大家都很了解了,是为了更好的方便其他文件(类)去调用本文件中的变量、属性和方法。而extern也是为了实现变量和函数的跨文件引用。所以很有必要详细讲解一下.h文件和extern的用法。
对于.h文件,我想大家都很熟悉了,不做过多的解释,但是有一点很重要:如果你在.h文件中声明全局变量(在OC中是不合法的:主要指在@interface ExternModel : NSObject和@end之间,当然如果在他们两个之外也是可以声明的)代码如下:
这是一个.h文件
#import <Foundation/Foundation.h> @interface ExternModel : NSObject // 这个是不合法的:因为OC的类会将这个全局变量当做成员属性来处理,而成员属性是需要加{}的,所以不合法 NSString *lhString;//声明全局变量的时候默认带有extern,这里必须显式声明 @end
所以正确的写法应该是:(如果还在.h中声明全局变量)
#import <Foundation/Foundation.h> @interface ExternModel : NSObject extern NSString *lhString;//这里由于带有extern所以会被认为是全局变量 @end
常用用法(.h结合extern联合使用):
1. 如果在.h文件中声明了extern全局变量,那么在同一个类中的.m文件对全局变量的赋值必须是:数据类型+变量名(与声明一致)=XXXX结构。并且在调用的时候,必须导入.h文件。代码如下:
ExternModel.h
#import <Foundation/Foundation.h> @interface ExternModel : NSObject extern NSString *lhString; @end
ExternModel.m
#import "ExternModel.h" @implementation ExternModel NSString *lhString=@"hello"; @end
调用的时候:例如:在viewController.m中调用,则可以引入:ExternModel.h,否则无法识别全局变量。
当然也可以通过不导入头文件的方式进行调用(通过extern调用)。
1.extern引用变量
extern具备与.h文件很相似的跨文件访问的功能,但是.h文件不单单局限于范文全局变量,而extern则必须是全局变量(静态+非静态)。
如果在其他文件中访问一个类的全局变量,可以不用导入.h文件,通过extern去直接访问。
例子:同样还是在ViewController.m中访问,此时不需要去导入头文件,代码如下(此时ExternModel代码如上):
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; extern NSString *lhString; NSLog(@"%@",lhString); }@end
输出结果:
2016-03-18 13:37:45.404 ExternTest[1490:180870] hello
可见在不通过.h的情况下去访问全局变量,可以通过extern实现。
其实也就是通过extern实现了跨文件操作,在一个model中定义一个全局extern变量,并在model.m文件中实现了对该变量的赋值,
那么我在viewController.m文件中,不用引入model.h文件,而是通过一个extern修饰变量就可以实现全局变量的访问.
2.extern声明
extern声明,仅适于修饰全局变量,不能去修饰其他的变量。一般情况下默认,定义的全局变量都带有extern,所以不过多解释。
static修饰全局变量
1.在全局变量前加static,全局变量就被定义成为一个全局静态变量(全局变量和静态全局变量的生命周期是一样的,都是在堆中的静态区,在整个工程执行期间内一直存在)
特点如下:
1)存储区:静态存储区没变(静态存储区在整个程序运行期间都存在);
2)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。非静态全局 变量的作用域是整个源程序(多个源文件可以共同使用); 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
好处:
1)不会被其他文件所访问,修改;
2)其他文件中可以使用相同名字的变量,不会发生冲突。
2.static修饰局部变量
在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
特点如下:
1)存储区:有栈变为静态存储区rw data,生存期为整个源程序,只能在定义该变量的函数内使用。退出该函数后, 尽管该变量还继续存在,
但不能使用它,也就是说static修饰的局部变量只能被访问一次,第二次调用含有该变量的函数的时候是不经过该局部变量的.(切记)
2)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。
- 修饰局部变量:
1.延长局部变量的生命周期,程序结束才会销毁。
2.局部变量只会生成一份内存,只会初始化一次。
3.改变局部变量的作用域。
- 修饰全局变量
1.只能在本文件中访问,修改全局变量的作用域,生命周期不会改
2.避免重复定义全局变量
3.static修饰函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用
好处:
1)其他文件中可以定义相同名字的函数,不会发生冲突
2) 静态函数不能被其他文件所用。
在我们这篇博客中主要关注于OC中三个关键字的常用方法。以下将是OC中常用方法的总结:
static和const的联合使用
- static与const作用:声明一个只读的静态变量
- 开发使用场景:在一个文件中经常使用的字符串常量,可以使用static与const组合
具体参考bolg:http://www.jianshu.com/p/2fd58ed2cf55 中的static与const的联合使用
extern和const的联合使用
作用:extern与const组合:只需要定义一份全局变量,多个文件共享。并且全局常量只被定义一次,分配一次内存空间。
代码如下:
ExternModel.h#import <Foundation/Foundation.h> @interface ExternModel : NSObject extern NSString * const lhString; @end
ExternModel.m
#import "ExternModel.h" @implementation ExternModel NSString * const lhString=@"hello"; @end
调用的时候通过导入.h文件进行调用。