码迷,mamicode.com
首页 > 其他好文 > 详细

1.5 万能指针 id

时间:2015-09-03 23:05:38      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

一. id

id是一种数据类型,并且是一种动态数据类型

数据类型的用途:

1. 定义变量

2. 作为函数的参数

3. 作为函数的返回值


默认情况下所有的数据类型都是静态数据类型

静态数据类型的特点:

在编译时就知道变量的类型,知道变量中有哪些属性和方法

在编译的时候就可以访问这些属性和方法

并且如果是通过静态数据类型定义变量,如果访问了不属于静态数据类型的属性和方法,那么编译器就会报错


应用场景:多态,可以减少代码量,避免调用了子类特有的方法需要强制类型转换

  1. id obj1 = [[Person alloc] init];
  2. [obj1 sleep];
  3. [obj1 test]; // Person类的私有方法
  4. id obj2 = [[Person alloc] init];
  5. [obj2 eat];
  6. [obj2 test]; // Person类的私有方法

为了避免动态数据类型引发的运行时的错误,一般情况下如果使用动态数据类型定义一个变量,在调用这个对象的方法之前会 进行一次判断,判断当前对象是否能够调用这个方法

1. 判断指定的对象是否是某一个类,或者是某一个类的子类

  1. id obj = [[Student alloc] init];
  2. if (obj isKindOfClass:[Student class]) {
  3. // 如果obj对象是Student类创建出来的或者是Student的子类创建出来的对象调用父类的eat方法
  4.   [obj eat];
  5. }

2. 判断指定的对象是否是当前指定的类的实例

  1. id obj = [[Student alloc] init];
  2. if (obj isMemberOfClass:[Student class]) {  
  3.   // 判断对象obj是否是Student类创建出来的对象,如果是调用类的对象方法    
  4.   [obj eat];
  5. }

二. new的实现原理

1. 创建对象new做了三件事情:

1>. 开辟存储空间  + alloc 方法;

2>. 初始化所有的属性(成员变量) - init 方法;

3>. 返回对象的地址


2. + alloc做了什么事情

1>. 开辟存储空间;

2>. 将所有的属性设置为0;

3>. 返回当前实例对象的地址

  1. Person *p1 = [Person alloc];


3. - init做了什么事情

1>. 初始化成员变量,但默认情况下init的实现是什么都没有做;

2>. 返回初始化后的实例对象的地址

  1. Person *p2 = [p1 init];
注: + alloc 和 - init 返回的实例对象的地址是同一个地址

三. 构造方法

在OC中init开头的方法,我们称之为构造方法

构造方法的用途: 用于初始化一个对象,让某个对象一创建出来就拥有某些属性和值


1. 重写init方法,在init 方法中初始化成员变量

1>. 必须先初始化父类,再初始化子类

2>. 必须判断父类是否初始化成功,只有父类初始化成功才能继续初始化子类

3>. 返回当前对象的地址

  1. - instancetype init
  2. {
  3.   if (self = [super init]) {
  4.       _age = 10;
  5.   }
  6.   return self;
  7. }

2. instancetyp和id的区别

instancetype == id == 万能指针 == 指向一个对象

id 在编译的时候不能判断对象的真实类型

instancetype 在编译的时候可以判断对象的真实类型


1>. id和instancetype除了一个在编译时不知道真实类型,一个在编译时知道真实类型

2>. id可以用来定义变量,可以作为返回值,可以作为形参,instancetype只能作为返回值

注:以后但凡自定义构造方法,返回值尽量使用instancetype,不要使用id


3. 自定义构造方法 (init自定义构造只用初始化自己的成员变量,父类的父类来处理)

  1. - (instacetype)initWithAge:(int)age andName:(NSString *)name
  2. {
  3.   if (self = [super init]) {
  4.     _age = age;
  5.     _name = name;
  6.   }
  7.   return self;
  8. }
  // NSLog输出%@ 最好重写 - (NSString *)description;
  1. - (NSString *)description
  2. {
  3.   return [NSString stringWithFormat:@"age = %i, name = %@", _age, _name];
  4. }


4. 自定义类工厂方法

1> 类构造方法:initWith.....

  1. - (instancetype)initWithAge:(int)age andName:(NSString *)name
  2. {
  3.   if (self = [super init]) {
  4.     _age = age;
  5.     _name = name;
  6.   }
  7.   return self;
  8. }
2> 类工厂方法:类名开头.....
  1. + (instancetype)personWithAge:(int)age
  2. {
  3.    Person *p = [[self alloc] init];
  4.    p.age = age;
  5.    return p;
  6. }
四. 类的本质

技术分享

五.SEL类型

1.创建一个人对象

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

2.agesetter方法封装成SEL

  1. BOOL b = [p respondsToSelector:sel];
  2. NSLog(@"%i", b);

3.判断Person对象方法中中是否存在 - 号开头的setAge:方法

  1. BOOL b = [p respondsToSelector:sel];
  2. NSLog(@"%i", b);
4.判断Person类方法中是否存在 + 号开头的setAge:方法
  1. b = [Person respondsToSelector:sel];
  2. NSLog(@"%i", b);

5.通过performSelector调用有参数的方法, 那么参数必须是对象类型

  1. SEL sel1 = @selector(setName:);
  2.        
  3. [p performSelector:sel1 withObject:@"jack"];
  4. NSLog(@"name = %@", p.name);






1.5 万能指针 id

标签:

原文地址:http://www.cnblogs.com/Xfsrn/p/4780784.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!