• 问题总会出现,不过解决问题的方法也会出现!!!

OC基础学习笔记05

学习笔记 小雨 810次浏览 已收录 0个评论

—— ——-

2-传统的get和set方法

定义一个Student类,拥有一个成员变量age和对应的get、set方法

Student类:

OC基础学习笔记05

Student类实现:

OC基础学习笔记05

调用:

OC基础学习笔记05

打印结果:

OC基础学习笔记05

3-点语法介绍和使用

  1. 使用“点语法”

OC基础学习笔记05

注意:

  1. 把原来的[stu setAge:10]替换成stu.age=10。这两种写法是完全等价的。即这里的stu.age并不是代表直接访问stu对象的成员变量age,而是编译器遇到stu.age=10的时候会自动将代码展开成[stu setAge:10]

OC基础学习笔记05

  1. 把原来的int age=[stu age];替换成了int age=stu.age。这两种写法又是完全等价的,stu.age并不是直接访问stu对象的成员变量,而是编译器遇到int age=stu.age的时候会自动将代码展开成int age=[stu age];

OC基础学习笔记05

  1. OC点语法的本质是方法调用,不是直接访问成员变量。至于这个点语法代表的是get方法还是set方法,那就取决于你是取值还是设值(也可以理解为点语法是在“=”的左侧还是右侧,左侧:如stu.age=···.这就是调用set方法,右侧···=stu.age这就是调用get方法),取值就是get方法,设值就是set方法

2、“点语法”验证

只需要在get和set方法中用NSLog();打印内容测试。

4-点语法使用注意事项

  1. 点语法陷阱
  2. OC中有个self关键字,作用跟this关键字类似。

OC基础学习笔记05

这是错误的,会造成死循环,因为OC点语法的本质是方法调用,所以上面代码相当于:

OC基础学习笔记05

下面的使用方法也是一个死循环:

  1. 在get方法中,return self.age;相当于是[self age];
  2. 点语法注意

点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开相应的方法。切记点语法的本质是转换成相应的set和get方法,如果没有set和get方法,则不能使用点语法。

5-@property关键字介绍及使用

  1. 基本概念

@property是编译器的指令

什么是编译器指令,编译器指令就是用来告诉编译器要做什么

@property告诉编译器声明属性的访问器(getter/setter)方法

这样的好处是:免去我们手工书写get和set方法繁琐的代码

2、@property用法

@property 类型名 方法名;

如:@property int age;

相当于进行了age的set和get方法的声明

-(void)setAge:(int)age;

-(int)age;

OC基础学习笔记05

OC基础学习笔记05

此时会默认的操作

_age这个实例变量

OC基础学习笔记05

6-@property使用注意事项

在老式的代码中,

@property只能写在@interface@end中,

@property用来自动生成成员变量的get/set方法声明(xcode4.4以前)

告诉property要生成的get/set方法声明的成员变量类型是什么

告诉property要生成的get/set方法是那个属性的,属性名称去掉下划线

如果写成了@property int _age;

OC基础学习笔记05

get方法

OC基础学习笔记05

7-@synthesize关键字介绍和使用

1、@synthesize用法

(1)@property int age;@synthesize age;表示生成.h中变量age的get和set方法

注意:

如果@synthesize 变量名要先在.h文件中声明

@property int age;@synthesize age;展开如下形式:

OC基础学习笔记05

注意:错误用法,只写了synthesize,没有写@property,也没有定义变量NSString*name;

OC基础学习笔记05

正确用法:

先定义变量int age;

使用@property age;声明方法

OC基础学习笔记05

使用@synthesize实现方法

OC基础学习笔记05

  1. 注意事项

@property和@synthesize搭配使用,用于简化set和get方法的定义和实现

8-@synthesize指定实例变量赋值

@property int a; @synthesize a=_b; 表示用a的set和get方法,修改属性b的值

相当于下面代码:

-(void)setAge(int)a{

_b=a;

}

-(int)a{

return _b;

}

9-@property增强使用

只使用@property进行声明,类自动帮你实现

Xcode4.4以后property做了增强

帮助我们自动生成get/set方法的声明

帮助我们自动生成get/set方法的实现

如果没有手动声明成员变量property会在.m文件中自动帮我们生成一个_开头的成员变量

OC基础学习笔记05

注意点:如果想让子类继承父类的成员变量,还是必须在.h中手动写成员变量

.h文件

@property int score;

.m文件

首先生成一个 _score的变量(注意该变量是私有的)

-(void)setScore:(int)score{

_score=score;

}

-(int)score{

return _score;

}

10-property下重写get和set方法

手动实现:

  1. 如果手动实现了set方法,那么编译器就只生成get方法和成员变量;
  2. 如果手动实现了get方法,那么编译器就只生成set方法和成员变量;
  3. 如果set和get方法都是手动实现的,那么编译器将不会生成成员变量,并且报错。

OC基础学习笔记05

11-动态类型和静态类型

  1. 动态类型和静态类型

多态:允许不同的类定义相同的方法。

动态类型:程序直到执行时才能确定所属的类。

静态类型:将一个变量定义为特定类的对象时,使用的静态形态。

将一个变量定义为特定类的对象时,使用的是静态类型,在编译的时候就知道这个变量所属的类,这个变量总是存储特定类的对象。使用静态类型时,编译器尽可能的确保变量的用法在程序中始终保持一直,编译器能够通过检查来确定应用于对象的方法是由该类定义的或者由该类继承的,否则就会显示警告。静态类型能够更好的在程序编译阶段就指出错误。并且使用静态类型可以提高程序的可读性。

  1. 为什么要有动态类型?

多态的出现是为了让不同的类能使用同名的方法。这会让程序的可读性大大提高,也降低了编程难度。

编译时和运行时检查

因为存储在id变量中的对象类型在编译的时候是无法确定的,所以一些事情是需要在运行时才能够确定。

例如:类Dog只有一个run方法,而类Cat只有一个jump方法,那么下面这段代码在编译的时候就会出错

Dog *dog=[[Dog alloc]init];

[dog jump];

因为编译器知道dog是Dog类的一个对象,而当遇到[dog jump]消息的时候,编译器同样知道Dog类是没有jump方法的,所以在编译阶段就会提出警告。但是如果将代码换成下面的样子在编译阶段就不会出错

Animal *cat=[[Dog alloc]init];

[(Cat*)cat jump];

因为在编译阶段编译器并不知道cat中存储的对象的类型是什么,所以在运行的时候程序就会crash

12-id类型及应用场景

  1. 用NSObject访问子类对象方法

OC基础学习笔记05

  1. id类型

id是一种通用的对象类型,它可以用来存储属于任何类的对象,也可以理解为万年指针。

注意:在id的定义中,已经包好了*号。id指针只能指向os的对象。

id类型的定义

Typedef struct objc{

Class isa;

}*id;

局限性:调用一个不存在的方法,编译器会马上报错。

iOS5之后推出了instancetype类型

instancetype和id的异同

  1. 相同点

都可以作为方法的返回类型

  1. 不同点

  2. instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
  3. instancetype只能作为返回值,不能像id那样作为参数
  4. id类型应用场景

OC基础学习笔记05

13-动态类型检测

  1. 动态绑定

  2. 在objective-c中,一个对象内是否调用指定的方法不是由编译器决定而是由运行时决定,这被称作是方法的动态绑定。
  3. 在objective-c里,对象不调用方法,而是接收消息,消息表达式为:[receiver message];运行时系统首先确定接收者的类型(动态类型识别),然后根据消息名在类的方法列表里选择相依的方法执行,所以在源代码里消息也称为选择器(selector);
  4. 消息函数的作用

-首先通过第一个参数receiver,找到它的isa指针,然后在isa指向的Class对象中使用第二个参数selector查找方法:

-如果没有找到,就使用当前Class对象中的新的isa指针,到上一级的父类的Class对象中查找;

-当找到方法后,再一句receiver中的self指针找到当前的对象,调用当前对象的具体实现的方法(IMP),然后传递参数,调用实现方法。

-假如一直找到NSObject的Class对象,也没有找到你调用的方法,就会报告不能识别发送消息的错误。

2、动态类型检查方法

对象在运行时获取其类型的能力称为内省。内省可以有多重方法实现。

  1. 判断类型

-(BOOL)isKindOfClass:classObj 判断实例对象是否是这个类或者这个类的子类的实例。

判断实例对象是否是另一个类类型

OC基础学习笔记05

-(BOOL)isMenberOfClass:classObj判断是否是这个类的实例。不管是不是这个类的子类的实例。

OC基础学习笔记05

OC基础学习笔记05

+(BOOL)isSubclassOfClass:classObj判断类是否是指定类的子类

OC基础学习笔记05

14-判断对象能否响应指定的方法

-(BOOL)respondsToSelector:selector判断实例是否有这样方法

能响应run方法

OC基础学习笔记05

不能响应test方法

OC基础学习笔记05

+(BOOL)instancesRespondToSelector:判断类是否有这个方法。此方法是类方法,不能用在类的对象

OC基础学习笔记05

15-相应方法

-(id)performSelector:selector(应用selector指定的方法)

OC基础学习笔记05

-(id)performSelector:selector withObject:object(应用selector指定的方法,传递参数object)

SEL s1=@selector(run);

[dog performSelcetor:s1];

NSString *str=@”哈利”;

NSString *str1=@”红薯”;

//带有一个参数

[dog performSelector:@selector(eat:)withObject:str];

//带有两个参数

[dog performSelector:@selector(eat:andFood:) withObject:str withObject:str1];

OC基础学习笔记05

-(id)performSelector:selector withObject:object1 withObject:object2(应用selector指定的方法,传递参数object1和object2)

16-构造方法的概念

构造方法:用来初始化对象的方法,是个对象方法,-开头

重写构造方法的目的:为了让对象创建出来,成员变量就会有一些固定的值

1、构造方法的调用

完整的创建一个可用的对象:Person*p=[Person new];

new方法的内部会分别调用两个方法来完成3件事情;

  1. 使用alloc方法来分配存储空间(返回分配的对象)
  2. 使用init方法来对对象进行初始化
  3. 返回对象的首地址

可把new方法拆开如下:

  1. 调用类方法+alloc分配存储空间,返回未经初始化的对象

Person*p1=[Person alloc];

  1. 调用对象方法init进行初始化,返回对象本身

Person*p2=[p1 init];

  1. 以上两个过程整合为一句:

Person*p=[[Person alloc]init];

注意:

  1. init方法就是构造方法,是用来初始化对象的方法,注意这是一个对象方法,以减号开头。默认初始化完毕后,所有成员变量的值都为0。
  2. alloc

向某个类发送alloc消息的结果

为该类分配内存,以存放该类的全部实例变量

还将这块内存区域全部初始化为0

注意:

一个刚刚分配的对象并不能立即使用

需要先初始化该对象,然后才能使用它

但由于未进行初始化

随后可能出现一些不可预测的行为

17-重写构造方法

Objective-C的推荐init方法写法如下:

OC基础学习笔记05

-(id)init{

if(self=[super init]){

//为子类增加属性进行初始化

}

return self;

}

这里涉及了几个问题,

1、[super init]的作用

面向对象的体现,先利用父类的init方法为子类实例的父类部分属性初始化。

  1. self为什么要赋值为[super init]

简单来说是为了防止父类的初始化方法release掉了self指向的空间并重新alloc了一块空间。这时的话,[super init]可能alloc失败,这时就不再执行if中的语句。

  1. super作为消息的接受者的实质:

super并不是真正的指针,[super message]的实质是由self来接受父类的message。需要注意的是,[super message]中,message方法出现的self为[super message]语境中的self,即子类实例。

构造方法案例

OC基础学习笔记05

19-自定义构造方法

  1. 自定义构造方法的规范
  2. 一定是对象方法,以减号开头
  3. 返回值一般是id类型
  4. 方法名一般以initWith开头
  5. 自定义构造方法的代码实现

Person类的声明,其中声明了两个接收参数的自定义构造方法

OC基础学习笔记05

Person类的实现:

OC基础学习笔记05

Student继承自Person类,声明了一个接收三个参数的构造方法

OC基础学习笔记05

Student类的实现

OC基础学习笔记05

测试主程序

OC基础学习笔记05

  1. 自定义构造方法的注意
  2. 自己做自己的事情
  3. 父类的方法交给父类的方法来处理,子类的方法处理子类自己都有的属性

本博客内容既有转载自网络的内容,也有本作者原创内容,仅供学习与交流之用
如有侵权或者错误之处,请及时在下方留言!
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址