【Day01】
OC语言 面向对象
一、面向对象
Anything is Object.万物皆对象。
现实中的对象是一种客观存在,
程序中的对象是一片内存中的数据。
1.对象
现实中的对象学生
有什么?姓名、年龄
能干什么?学习
1.对象
计算机中的对象Student
属性(成员) age,name
方法(函数)study()
用解决现实中的问题的方法,来解决计算机问题。
2.类
设计(图纸)(梦想中)---努力实现--->楼(现实)
代码(文件) ---执行加载--->内存(数据)
类 ---实例化 --->对象
2.类
类是一种主观思想,是对我们需要解决问题的一种抽象,是创建对象的模型,就是类型,用户自定义类型。
对象就是具体的数据,计算机会把类->实例化->对象。
3.第一个面向对象程序
a.设计类Student 代码存在文件中,OC class。
一个类是由两个部分组成的 *.h文件和*.m文件
3.第一个面向对象程序
1).h文件 定义类的interface部分(声明)
@interface Student : NSObject
@property int age;//声明属性
-(void)study;//声明方法
@end
3.第一个面向对象程序
2).m文件 定义类的implemention部分(实现)
@implementation Student
//方法的定义、实现
-(void)study{
NSLog(@"学生执行了study方法");
}
@end
3.第一个面向对象程序
b.类的实例化->对象
1)main.m文件中的->main函数(程序入口)执行程序
2)能过类发送alloc,通过一个类创建对象,通过stu变量,找到内存的对象。
3)可以向对象发送消息(函数),此时对象就会响应消息,执行方法。
4)对象如果有属性,对象.属性 = 值,给对象的属性赋值
创建一个Point2类,有横坐标x、纵坐标y,能显示位置show方法,创建两位置,并显示。
【Day02】
二、方法
对象可以干什么,功能。
1.函数与方法有什么区别?
函数只是一个程序的代码段,与类无关系。
方法,类的一部分,代表对象可以干什么。
正常来讲,类必须实例化,方法才可以使用,实例方法,调用方法时,也叫做向对象发送消息。
.m:message
2.语法格式 语法格式与函数非常相似,但截然不同。使用方法时,在.h文件中声明,在.m文件中实现。
a.-(返回值类型) 方法名; //无参的方法 eg:-(void)method;
b.-(返回值类型) 方法名:(参数类型)参数名;//有参的方法
eg:-(void)method3:(int)num;
c.-(返回值类型) 方法名:(参数1类型)参数名1 :(参数2类型)参数名2 :(参数n类型)参数名n;//多参的方法
eg:-(void)method4:(int)arg1 :(int)arg2;
注:":"符号也是方法名的一部分
method、method3:、method4::。
d.*-(返回值类型) 部分方法名:(参数1类型)参数名1
部分方法名2:(参数2类型)参数名2
部分方法名n:(参数n类型)参数名n;
部分方法名起到提示作用,并不影响程序的执行
eg:-(void)printInfoWithAge:(int)age
andGender:(char)gender
andSalary: (double)salary;
三、实例变量
1.一个对象会有自己独特的数据和别的对象不同,这些数据会保存在一些特殊的变量中,这种变量叫实例变量。类的每个实例(对象)都有一份。
类 对象(实例)(引用)
内存中没有 内存中有
成员变量 实例变量
成员方法 实例方法
2.用一个类,创建出一个对象,那么我们就说这个对象就是此类的实例,一个类可以有很多实例(对象),每一个实例都拥有一个和其它实例不同的数据,这些数据保存在实例变量中。
3.实例变量的声明,可以放在.h文件中,也可以放在.m文件,实例变量就变为私有的,只有当前对象才可以访问。
方法也是一样,放在.h文件中声明,公有方法。
方法在.h文件中没有声明,私有方法,是不合法的。
四、属性
1.在OC中,属性提供了setter和getter方法,本质上属性就是方法,属性的值是由实例变量来保存的。
2.属性的本质
一般三个部分组成
a.保存属性值的实例变量 int _age;
b.setter和getter方法的声明与实现
1.)setter方法:方法名:“set”+属性名并首子母大写+“:”+和属性类型一样的参数,无返回值。age
-(void)setAge:(int)newAge;
2.)getter方法:方法名和属性名一样,没有参数,返回值类型和属性类型一样。
-(int)age;
c.setter方法和getter方法的实现
setter方法的实现主要用来给属性赋值的
getter方法的实现主要用来读取属性值的
对象.属性 = 值;=>会自动调用setter方法
变量 = 对象.属性;=>会自动调用getter方法
stu.age = 18;//给属性赋值 setter
NSLog(@“age:%d",stu.age);
//取属性值 getter
3.声明式属性
a.定义实例变量
b.声明式属性
1).h文件中 int属性类型 age 属性名
@property int age;
自动生成了setter和getter
2).将属性与实例变量关联在一起 .m文件中
@synthesize age = _age;
c.属性的使用
引用.属性 = 值;=>会自动调用setter方法
变量 = 引用.属性;=>会自动调用getter方法
4.IOS5.0以后,属性的声明简化了
a.省去了实例变量声明,会自动生成实例变量名为_属性名的实例变量
b.声明式属性
1).h文件中 int属性类型 age 属性名
@property int age;
自动生成了setter和getter
2).将属性与实例变量关联在一起 .m文件中
@synthesize age = _age;
c.属性的使用
引用.属性 = 值;=>会自动调用setter方法
变量 = 引用.属性;=>会自动调用getter方法
5.***IOS6.0开始,声明式属性又简化
a.省
b.
1)保留
2)省 @synthesize age = _age;
c.保留
6.属性的演变过程,如果你不满意,可以自己重写。
一、初始化方法
用来初始化对象的方法。
1.初始化方法的规则:
a.初始化方法都是以"init"开头的,无参的初始化方法叫"init",有参的都以"initWith..."开头。
b.初始化方法的返回值为"id"类型。(void*)
c.初始化方法的一般格式
super代表类的父类,[super init]是通知父类去做底层的初始化操作。
self代表当前对象或当前类,self就是当前对象的引用。(地址)
self = [super init];
if(self){//初始化,不一定成功,不成功值就为nil(NULL)
初始化对象的属性值...
}
return self;
d.初始化方法可以有多个,有参(一个参数、多个参数)、无参的。
e.执行无参的初始化方法
[[Student alloc]init]与[Student new]是等价的。
f.id类型
id类型是一种特殊的指针类型,类似void*,id类型其实就是一个指针变量,指向任何对象,在使用前必须类型转换。
Eg:
Student* stu = [Student alloc];
id stu2 = [stu init];
Student* stu3 = (Student*)stu2;
等价于:Student* stu =
[[Student alloc]init];
[stu3 study];
二、实例方法和类方法
1.只能通过实例调用的方法叫实例方法。"-"
2.只能通过类调用的方法叫类方法。”+"
3.实例方法与类方法区别
a.实例方法与实例有关系的,所以实例方法可以调用、读取实例中的实例变量或属性。
b.类方法与实例无关系的,所以类方法不可以调用、读取实例例中实例变量和属性。
c.在类方法中可以创建对象,当然访问该对象的实例变量和属性。
三、工厂方法
生产(创建)对象的方法,叫工厂方法。
类中经常会出现一些工厂方法,其目的是为了方便创建对象。
规则:
1.工厂方法一定是类方法
2.工厂方法返回id类型,因为要返回一个刚创建好的对象类似初始化方法。
3.工厂方法的方法名一定以类名开头,注意去除了前缀和首字母要小写。
1.创建一个Point2类,有横坐标x、纵坐标y,能显示位置show方法,创建两位置,并显示。
(重构,属性,初始化方法(无参、有参),工厂方法(无参、有参)。
2.创建TRPerson类,有age、sex、salary,能显示信息的普通方法show,创建两个人。(重构,属性,初始化方法(无参、有参),工厂方法(无参、有参)。
【Day03】
四、self关键字
代表当前对象或者当前类。
1.在实例方法中的self,通常来讲就是代表当前对象。
2.在类方法中的self,通常来来讲就是代表当前类。
五、编程规范
1.标识符
给变量、函数、类、方法、常量等起名字。
a.必须以_和字母开头
b.只能包含数字、_和字母
c.不能与关键字冲突
d.大小写敏感
e.长度是不限的
2.命名规范
a.类、分类、扩展、协议等类型起名时,一般加前缀(2~3个字母组成),并且每个单词的首字母大写。
b.驼峰标识:如果标识符由多个单词组成,每个单词的首字母大写。
c.属性、方法、变量的首字母小写,其后的每个单词的首字母大写。
d.常量一般大写,单词之间"_"隔开。
数字和字符是常量外,
const int MAX_NUM = 10;//常量
3.OC特有的代码风格
a.无参的初始化方法,"init"命名,有参的以"initWith … "开头。eg:
[[TRStudent alloc]init];
[[TRStudent alloc]initWithAge:18 andSex:'M'];
b.工厂方法,以小写的类名开头,有参的工厂方法,"小写类名With"开头。
[TRStudent student];
[TRStudent studentWithAge:18 andSex:'M'];
c.其它
一般方法的方法名不能以new开头,new开头的方法基本上是用来创建对象的。
4.补充
a.代码的结构性,一定要缩进。
(command(win)+a全选,control(ctrl)+i自动代码缩进)
b.当一个方法比较长时,可以用空行的方式,将方法分成几个模块。
六、内存管理
1.进程空间
代码区:只读。
*堆:自己创建、自己回收释放,对象是保存在堆区的。
全局区:进程启动时分配,进行结束时释放。
栈:局部变量,自动创建、自动释放空间
内存管理:主要对堆内存进行管理,所谓的管理,内存的分配(创建)和释放(回收)。
2.IOS的内存管理方式
RC:Reference(引用)Counting(计算器)
a.MRC Maual手动
b.***ARC Automatic自动
3.MRC(手动内存管理)
a.每个对象都有自己的引用计数器,引用计数器是用来计算对象被引用的次数。
b.创建对象时(alloc、new),此时通知引用计数器为1 。
c.当你需要使用一个别人创建好的对象时,为了防止在使用此对象期间别人释放了这个对象,我们要将此对象的引用计数器加1(程序员通知引用计数器),只要给对象发送retain消息,引用计数器就会加1.
d.当你使用的对象不再使用时,你有责任通知引用计数器减1,发送release消息。
e.当对象的引用计数器为0时,说明已经没有任何引用指向对象,对象就会被系统自动销毁,系统销毁对象之前,会自动向对象发送一条消息"dealloc"消息,对象所占的空间就会被释放[super dealloc],千万不要自己去调用dealloc消息。
f.可以使用"retainCount消息",查看当前引用计数器的值。
g.当你指向的对象,不再使用时,如果忘了发送release消息,内存泄漏。(资源浪费)
h.当引用指向对象,已经不存在了,继续向对象发送消息,会发生问题,异常、crash
i.没有相应内存空间的指针,野指针。
j.会使用空指针,解决野指针问题,而在OC中,向空指针发送消息,是不会报错的。stu = nil;(C语言中 stu = NULL)
1.声明->类
TRCpu TRMEM TRComputer(TRCpu TRMem)
初始化方法 工厂方法
2.使用->类实例化对象
向对象发送消息 .结果屏幕输出结果
3.内存管理MRC
【Day04】
二、autoreleasepool 自动释放池
1.池 节约空间 节资源 "共享"。
2.通过自动释放池来管理对象,只需要一个自动释放池,可以管理很多对象,当自动释放池结束的时候,会自动向池中的每个对象都发送release消息。
3.自动释放池是可以嵌套的,会先释放里面的,再释放外面的。
4.工厂方法通常都实现了发送autorelease消息。
三、面向对象的三大特征: 封装、继承、多态
1.封装
封装属性和方法放在一个对象中,只给外界公开访问的接口,而且把具体实现隐藏起来。主要目的增加可读性、可维护性、可扩展性。
在OC中,把需要公开的属性、方法定义在声明中,.h文件中interface部分,而把不需要公开的属性、方法定义在.m文件中implementation部分,隐藏起来。
封装的好处:
1)代码结构更清晰
2)可以和第三方合作,但又保护了源代码,避免泄漏。
2.OC中实例变量的处理:
一般情况下,实例变量是不能公开的,所以实例变量应用定义在implementation部分(私有的),除非你需要直接在子类中访问,可以定义在interface部分,可以使用以下语法声明实例变量,来控制实例变量的访问范围。
a.变量的访问范围:
@public 可以在任意位置访问
@package 可以在包内部访问,一个项目一定是在同一个包下。
@protected 可以在本类内部和子类内部访问
@private 只可以在本类的内部分访问
b.默认实例变量修饰符:@protected
c.可以通过"->"可以访问实例变量(但不推荐),通过.语法(属性)来访问实例变量。
3.封装中的方法
a.如果.h文件中,未声明方法,此方法就是私有的,在其它文件中访问该方法是不合法的(必须不能访问)。
b.如果.h文件中,声明方法,此方法就是公有的,在其它文件中可以访问该方法的。
4.继承
a.概念
继承是一种代码复用技术,是类与类之间的一种关系。
A类继承B类,A类中就直接拥有B类中的属性和方法。我们就把A类叫B类的子类(派生类),把B类叫做A类的父类(基类)。
4.继承
b.继承方式
单继承
一个类只能继承一个父类。 爷<-爸<-你
OC Java C#
多继承
一个类可以有多个父类
C++
4.继承
c.继承的语法
@interface 类:父类
(所有类都继承于NSObject)
@end
d.继承是一种关系
继承是类与类之间的关系,是一种"is a"关系。
狗是动物 狗:动物
e.方法的覆盖(重写)
子类对父类继承的方法不满意,可以在子类中重写父类的方法
1)方法名相同
2)参数类型相同
3)返回值类型相同
f.如果重写父类的方法,优先调用子类的方法,如果子类没有重写父类的方法,则调用父类的方法。
一、继承的缺陷
1.提高了程序的复杂度,维护性和扩展性降低
2.破坏类的封装性
二、为什么使用继承
1.代码复用
2.制定规则
3.为了多态
三、组合和*聚合
复用代码更好的方法是组合和聚合,而不是继承。
组合和聚合也是类与类之间的"has a"的关系。
Computer has a cpu.
a.继承 一个对象
b.组合 代码书写习惯
优点:保留了封装性、操作便利 缺点:灵活度不够。
生命周期:Cpu和Computer封装性是独立的,生命周期是一致的,一起存在,一起销毁。高耦合(依赖)在一起。
c.*聚合
保留封装性
优点:灵活度高 缺点:操作欠佳
生命周期:Cpu和Computer生命周期不一致,低耦合,方便Cpu的替换。两个对象,各过各的。
————————
【Day05】
四、多态
1.概念
多种形态,引用的多种形态。
对于一个引用变量,可以提向任何类的对象
对于一个父类的引用(类与类之间有一种关系,继承关系),可以指向子类,也可以向本类,指向的类型不同。当通过此引用向对象发送消息,调用的方法是不同的,此时方法的调用就是多态。
a.类与类之间有关系,继承关系。
b.父类的引用可以指向子类的引用,或者本类的引用。
c.父类的引用指向子类的对象,发送消息,调用的是子类对象的方法。
父类的引用指向本类的对象,发送消息,调用的是本类对象的方法。
2.编译期类型和运行期类型
a.在多态下,父类的引用可以指向子类的引用,当编译的时候,编译器无法确定指向的对象是什么类型,所以编译器会将引用当做父类类型引用编译检查。
b.在调用方法时,却是子类对象。(子类类型创建的空间)。
总结:TRAnimal* animal=[[TRDog alloc]init];
编译时,把TRDog类型当成TRAnimal类型编译。
[animal eat];
运行时,调用的是TRDog类型的对象。
3.多态可以用在参数,参数多态
4.多态可以用在返回值类型,返回值多态 工厂方法
5.多态可以用在数组上
————————
【Day06】
OC Category 分类
分类就是类的补充和扩展部分
补充和扩展的每个部分就是分类
分类本质上是类的一部分
分类是给特定类添加能力
分类的定义
分类也是以代码的形式保存在文件中
分类文件命名 主类类名+分类类名
分类文件也分为*.h文件和*.m文件
*.h文件存放分类的声明部分内容
@interface 主类类名(分类类名)
//添加方法声明
@end
.m文件存放分类的实现部分内容
@implementation 主类类名(分类类名)
//添加方法实现
@end
分类中是不可以创建实例变量的,自然也不可以创建属性。
在分类中是可以访问主类的属性,但不可以访问主类的实例变量。
分类的实现步骤:
1.创建分类
2.调用分类中的方法
3.#import 分类
分类的使用
分类可以给一个自定义类添加功能
分类还可以给一个系统类或第三方类添加功能
二、扩展(延展)
1.概念
扩展其实就是分类的一种特殊形式,扩展是没有名字的。
2.使用方式
a.扩展中可以声明实例变量,所以可以声明属性
b.扩展通常定义在文件的.m中,不能分开。
c.扩展是用来声明私有的属性和方法
区别:
分类:是不可以声明实例变量,通常是公开的,文件名通常为:"主类类名+分类类名.h"
扩展:是可以声明实例变量,是私有的,文件名通常为:"主类类名_扩展标识.h",注意扩展没有名的。
三、协议
1.概念
协议就是规则,定义一个协议就相当于制定规则。
OC中类可以遵守协议,遵守了一个协议的类相当于拥有了一种能力。
2.语法
@protocal 协议名
@required 声明必须遵守的属性和方法
@optional 声明可选(可以)遵守的属性和方法
默认 @required
@end
3.一个类遵守一个协议
a.@interface 类名(分类类名):父类名<协议名>
b.实现协议中声明的方法
4.使用协议类型的引用指向实现了协议或者遵守了协议的对象
id<TRProtocol> p = [[MyClass]init];
[p …];可以向协议的引用发送消息,只能发送协议要求的消息。
5.协议的继承
协议的继承相当于协议的合并。
子协议 父协议
@protocol TRTarena2 <TRTarena>
-(void)learn;
@end
6.一个类可以同时遵守多个协议,协议之间使用","分隔符分开。
@interface TRStudent : NSObject<TRTarena,TRTarena3>
7.协议的使用和多态相类似,可以用于数组、参数、返回值类型,只不过多态返回的对象,一定要有继承关系,协议类型返回的对象,一定要有遵守协议或实现协议。
四、内存管理ARC自动引用计数器管理
1.ARC IOS5.0以后才支持,IOS7.0以后,强制使用ARC。
2.ARC "Automatic" Refercences Counting
3.原理
依然使用引用计数器来管理内存,只是引用计数器的操作方式不同,由程序员发送消息转换为“编译器”帮我们自动发送消息,会在合适的位置自动加入retain、release、autorelease消息来进行计数管理,ARC是一种编译期语法。
4.使用ARC
a.在ARC中,程序中不能出现retain、release、autorelease…
b.在ARC中,程序不能在dealloc方法中显示调用父类的dealloc方法,一切在MRC中和内存相关的操作,ARC中都不能使用。
5.强引用
a.在程序中定义的引用,默认为强引用,所谓的强引用指向一个对象时,对象的引用计数器会自动加1,当引用超出作用域"{}",对象的引用计数器就会减1.
b.定义强引用
__strong TRStudent* student = [TRStudent alloc]init];
c.当一个对象被引用指向时,此对象会隐式的retain一次,当强引用超出作用域时,指向的对象会隐式的发送release消息一次。
d.引用在使用的时候,会根据作用域的范围,自动做加1或减1的操作。
6.弱引用
a.定义弱引用
__weak TRStudent* student;
b.仅仅就是指向对象,但不会隐式的发送retain消息,出了作用域也不会发送realse消息。
c.XXX当一个弱引用指向的对象,未销毁时,向对象发送消息,此弱引用会自动的变为强引用。(xcode4.x)版本
d.当一个弱引用指向的对象被销毁时,弱引用本身会自动的赋值为空。(nil)
zeroing weak reference
四、内存管理ARC自动引用计数器管理
7.定义属性的时候,内存管理的描述
@property(nonatomic,strong)…;
@property(nonatomic,weak)…;
重构ARC Student与Book的故事。
8.其它修饰关键字
@property(nonatomic,unsafe_unretained)int age;
a. unsafe_unretained等同于"assgin",功能和__weak几乎一样,唯一不同,没有"zeroing weak reference",通常使用在基本数据类型。
b.__autoreleaseing 用在方法的返回值,将返回值的对象放入到自动释放池中。
+(id)student{
__autoreleaseing TRStudent* student = [[TRStudent alloc]init];
return student;
}
9.dealloc方法
a.在ARC下,dealloc方法不允许调用父类的dealloc方法,当然也不允许向任何对象发送release消息,所以说dealloc方法几乎无用。
b.在一些特殊情况下需要重写dealloc方法。
1)在类中使用了C语言中的函数malloc分配内存。
2)在类中使用了C++语言中的函数new等方式创建内存空间。
此时需要在dealloc中对这些特殊的空间进行释放。
10.声明引用自动置空
a.在ARC下,如果定了一个引用没有赋值,编译会自动的初始化设置引用为空值。TRStudent* student;
b.为了尊重C语言的规范,基本数据类型没有初始化值,依然是垃圾值。
11.MRC和ARC混用
a.把MRC的代码转换成ARC的代码(手动)
retain=>strong
release、autorelease、[super dealloc]删除掉。
b.xcode提供了自动将MRC转换成ARC的功能。
菜单栏(Edit)->Refacotor(重构)->Convert to Objective-C ARC
c.在ARC项目中继续使用MRC编译的类
在编译选项中标识MRC文件即可
"-fno-objc-arc"
d.在MRC项目中继续使用ARC编译的类
在编译选项中标识MRC文件即可
"-fobjc-arc"