特有语法


@property

  1. 作用:自动生成getter、setter方法的声明
  • 因为是生成方法的声明,所以应该写在@interface类的声明之中。
  1. 语法:
@property 数据类型 名称
  1. 原理
  • 编译器在编译的时候,会根据@property生成getter和setter方法
  1. 使用@property注意
  • @property的类型和属性的类型一致
  • @property的名称和属性的名称一致(去掉下划线)

@synthesize

  1. 作用:自动生成getter、setter方法的实现
  • 因为是生成方法的实现,所以应该写在类的实现之中。
  1. 语法:
@synthesize  名称
  1. 原理
  • 编译器在编译的时候,会根据@synthesize实现getter和setter方法
  • 实现的方法:将参数直接赋值给自动生成的那个私有属性(不是自己写的),并且没有任何逻辑验证
  1. 希望@synthesize不要去自动生成私有属性
//这样就不再自动生成了
@synthesize age = _age;
  1. 批量生产
  • 如果类型一致
@property 类型 名称1,名称2;
@synthesize 名称1=_名称1,...;
  1. 现在只写@property就可以实现生成和实现了
  • 生成时没有做任何逻辑验证
  • 所以,我们可以重写setter来自定义验证逻辑,如果重写了setter,还会自动生成getter,重写getter也会自动生成setter
  • 如果两个同时重写,那么就不会自动生成了
  • 可以继承,但在子类的内部无法直接访问,但可以用getter和setter访问

  1. 静态类型:指的是一个指针指向的对象是一个本类对象
  2. 动态类型:指的是一个指针指向的对象不是本类对象
  3. 编译检查:看指针所属的类型中有没有这个方法
  4. 运行检查:看这个对象中是否有这个方法
  5. LSP:任何的指针可以指向任意的对象,编译器不会报错
  6. 判断指针指向的对象中是否有这个方法可以执行
  • 第一种方法 ,判断对象中是否有这个方法可以执行
    BOOL b1 = [p1 respondsToSelector:@selector(age)];
    if(b1==YES){
        [p1 sayHi];
    }
  • 第二种方法,判断指定的对象是否为指定类的对象或者子类对象
    BOOL b1 =[p1 isKindOfClass:[NSObject class]];
    NSLog(@"b1=%d",b1);
  • 判断对象是否为指定类的对象,不包括子类
    BOOL b2 = [p1 isMemberOfClass:[Person class]];
    NSLog(@"b2=%d",b2);
  • 判断一个类是否为另外一个类的子类
[Student isSubclassOfClass:[person Class]];
  • 判断类中是否有指定的类方法
[Person instanceMethodForSelector:@selector(satHi)];

NSObject

  1. 可以指向任意的OC对象(万能指针,所以OC类的父类)
  2. 缺点:如果要调用指向的子类对象独有的方法,就必须要做类型转换

id指针

  1. 万能指针,在定义的时候已经加了*,所以声明时不用加*。
  2. NSObject和id的异同。
  • 相同点:万能指针 都可以执行任意的oc对象。
  • 不同点:NSObject指针 会做编译检查,id类型不会做编译检查
  1. 注意
  • id指针不能使用点语法,只能调用方法
  • 如果想要使用万能指针id比较方便
  1. 父类中的类方法创建一个父类对象返回
  • 如果返回值写为父类类型的,那么子类来调用这个方法得到的就是父类指针,- - 解决方法:把返回值改为id类型的
  • 方法的内部创建对象的时候,不要写死,因为写死创建的对象就固定了。我们希望那一类来调用这个方法就创建那一个类的对象。把类名写为self,那一个类来调用这个方法,self就指的是那一个类。创建的就是那一个类。
+(id)person
{
	return [self new]
}
  • 方法的返回值是id类型的,问题就是任意指针都可以接收这个方法的返回值。编译器连个警告都没有。如果方法的返回值是instancetype,代表方法的返回值是当前这个类的对象。
+(instancetype)person
{
	return [self new]
}
  1. 使用建议
  • 如果方法内部是在创建当前类的对象,不要写死成类名【类名 new】,而是用self代替
  • 如果方法的返回值是当前类的对象,也不要写死,而是写instancetype
  1. id和instancetype的区别
  • instancetype只能作为方法的返回值,不能在别的地方使用,id既可以声明指针变量,也可以作为参数,也可以作为返回值。
  • instancetape是1个有类型的,代表当前类的对象
  • id是一个无类型的指针,仅仅是一个地址,没有类型的指针
学习