super init重构 id 指针 NSObject指针 intancetype指针

OC基础day06

     **问题  :
     init初始化初始化默认值
     和 类初初始化的区别
    调用时 子类父类类方法是必须要用父类的类方法名
    才能调用
        而init子类也可以调用init对象方法名**
  • NSObject 是所有类的根类

  • super

    • 重写: 重新实现父类继承过来的方法
    • super 可以在子类中调用父类的方法
    • super 能不能再类方法中使用?
      • 可以 如果子类的类方法中使用那么super调用的就是父类的类方法
      • 在子类调用对象方法中用super 就是调用的父类的对象方法
  • 私有变量: @private修饰的叫做私有变量
  • 真 私有变量就是写在.m中声明的成员变量
  • 私有方法 在 .m 中实现而不再 .h 中声明
  • description方法
    • NSLog(@”%@”,对象的指针);
    • %@打印对象的指针的时候 本质上
      • 调用了这个对象的 - (NSString *)description 返回一个字符串 在把这个字符串打印到控制台
      • -(NSString *description 是在NSObject他的默认返回值”<对象所属的类名:对象的地址>”
      • 所以我们有时候需要重写 这个类的-(NSStrong *)description
      • 目的、: 是用%@可以快速打印这个对象信息
  • 里氏替换原则
    • 父类指针 可以指向子类的对象
  • 多态
    • 对于同一个行为的多种变现形式
      • 有继承关系
      • 有方法重写
      • 有父类指针指向子类对象
  • 类的本质: 是一个对象 是一个名字叫做Class 这个类的对象
    • [对象 class]
    • [类名 class]
  • SEL是一种书数据类型
    • SEL sel; SEL 使用来保存类的方法
    • SEL sel = @selector(方法名);
      -

* 点语法*
- 点语法 :相当于调用方法

对象名.name = @"xxx";
//相当于  [对象名 setName:@"xxx"];

NSString *name = [对象名 name];
NSString *name = 对象名.name;
  • 总结: 点语法的适应

    • 如果点语法出现在赋值符号左边相当于赋值
    • 那么这个语法相当于 setXxx方法

    • 如果点语法出现在赋值符号右边相当于取值

      • 那么相当于 使用 getXxx
  • 点语法注意事项

    • 点语法 : 是Xcode的特性 在编译之前 xcode会把点语法替换成对象方法
    • 对象.那么 = @”zhangSan”=======>[对象 setName:@”zhangSan”];
    • 所以说在使用点语法之前 必须有对象方法
      @property的使用
  • 在xcode 4.4之前 @property 只能生成setter和getter的声明
  • @synthesize只能生成 setter和getter的实现
  • 必须两个同时使用 生成的是私有属性
    *@property增强
  • 格式: @perperty 数据类型 去掉下划线的属性名
    • 自动生成getter和setter的声明和实现
    • 不会生成不带下划线,而会生成带有下划线的(如果不村子啊)
  • 使用@property注意
    • 生成的数据类型是 带有下划线的真有属性 @protected
    • 生成的setter和getter是直接赋值和直接返回的
    • 所以如果想要进行逻辑判断 直接在.m中做逻辑判断
    • 如果同时声明加逻辑判断 就需要在.m中添加一个属性
      任意的指针可以指向任意的对象
  • OC是一门弱语言 编译器对源代码的容错性较强 一些逻辑错误只是报警告不会报错
  • 若语言的缺点
    • 如果有逻辑错误编译可以通过 运行不通过
  • 动态类型和静态类型
    • 静态类型: 什么样的指针就指向什么样的对象
    • 动态类型: 指针的类型和指针指向的真是类型不一致
      编译检查 运行检查
  • 什么是编译检查

    • 编译检查: 程序运行之前的检查, 就看这个指针定义的时候类型是否拥有某个方法/属性
    • 运行检查:程序运行过程中检查, 见这个指针指向的对象的类型是否拥有某个方法的实现
  • 编译看左边 运行看右边

        口诀:
    编译时看左边,运行时看右边
    

    NSString * str = [Dog new];//不会报错,OC弱语法

    调用方法:
    [str eat];//编译的时候报错

    [str length];//编译的时候不会报错,运行时报错

    [(Dog *)str eat];//编译的时候 不会报错,运行时也不会报错

    报错信息:
    reason: ‘-[Dog miaomiao]: unrecognized selector sent to instance 0x100501430’
    这种信息通常表示 运行时对象没有 上面说的那个”miaomiao”方法
    编译的时候 编译器说了算
    运行的时候 运行时说了算

NSObject万能指针
- NSObject是一个万能指针
- 可以指向任何对象,编译不会报错(因为OC是若语法)也不会警告(里氏替换原则)

#import "HMPerson.h"
//HMPerson类中有一个方法 叫做 - lenght
@interface HMPerson : NSObject
@property NSString * name;

- (NSUInterger)length;


@end

@implementation HMPerson


- (NSUInterger)length
{
    return 10;
}

@end

int main(int argc, const char * argv[]) {

    NSObject *obj = @"1234";//万能指针 指向了一个 OC字符串对象

//    [obj length];报错 因为编译时只看指针的类型,没有lenght方法 所以报错
    unsigned long len = [(HMPerson *)obj length];

    NSLog(@"%lu",len);//编译直接报错 解决[(NSString *)obj length]
    return 0;
}
"NSObject * 指针有一个缺点

    NSObject * 指针指向了一个自己定义的对象的时候,想通过这个指针调用自己定义的对象的方法时
    必须强转,避免编译器报错

id指针
- id类型 是一个typedef过的指针类型
- 所以声明的时候不需要加*
- id和NSObject* 都是万能指针 他们的区别在于
- 指针类型的NSObject* 编译的时候会做编译检查 如果想编译通过必须进行强制转换
- id指针 编译时直接通过
- id指针的缺点
- 优点: 不做任何编译检查
- 缺点: 不做任何编译检查
- 不能通过 id 指针 使用点语法 但可以使用 getter和setter方法

instancetype
- 写一个与类同名的类方法/带有参数的方法

    + (Person *)person;//personWithXxx
    + (Dog *)dog;
  • 返回值如果是这个类的本身的对象 那么就是instancetype 表示这个类本身的对象
  • id和instancetype的区别
    • instancetype 只能作为方法的返回值
    • id指针 是一个万能指针 通常id可以用来定义一个可以指向任何对象的指针变量
      -

在对象方法中使用self创建当前类的对象

1.Person * pp = [Person new];

我要拿到Person类的类对象
[pp class];
[Person class];

2.在Person类中有一个方法
- (void)test
{
    //在此方法中创建一个Person对象
    //1.Person * p1 = [Person new]
    //2.Person * p2 = [self new];//不行,对象方法中self'表达对象
    //先获取到类对象
    Class clazz = ;

    [clazz new];//就是当前类的对象

//    合成一句话
    [self.class new];//self.class ===>[self class]

}

动态类型检测

  • 判断一个指针所指向的对象 能不能响应这个方法(可以有声明但是必须有实现)
 BOOLrespondsToSelector:(SEL)aSelector;
 Person *pp = [Person new];
 [pp respondsToselector:@selector(方法名)];*****
 ```

 - 判断一个对象 是不是指定类的对象 或者它子类的对象

(BOOL)isKindOfClass:(Class)aClass;

- 判断一个对象 是不是指针类的对象 不包括子类对象

(BOOL)isMemberOfClass:(Class)aClass;

- 判断一个类 是不是指定类的子类

+(BOOL)isSubclassOfClass:(Class)aClass;



**构造方法**
- new方法的内部干了三件事
    - 在堆区开辟空间
    - 初始化
    - 返回空间地址
- 其实new方法内部什么都没干,调用了两个方法
     - alloc方法==> 1>在堆区开辟空间
    - init方法==>  2>初始化
    有一个类 Person类
创建对象 Person * p1 = [Person new];
    Person * p2 = [[Person alloc] init]
    /*
     Person * pp = [Person alloc];
     Person * zhangsan = [pp init];

     */

**重写init方法**
- 重写init方法的目的
    - init方法是在NSObject中定义,默认实现给属性赋值都是0
    - 为了让一个对象创建出来就有固定的值 我们必须重写构造方法

//代码必须按照以下代码
- (instancetype)init
{
if(self = [super init])
{
// 子类自己要写的一些代码
self.name = @”lidain”;
}
return self ;
}

“`

  • 目的: 初始化对象的时候我们可以指定

自定义构造方法
- 可以根据需求 自己指定初始化对象后的属性值
- 自定义方法的规范
- 必须是 initWithXxx开头
- 也要在initWithXxx 方法中用super方法
- 自定义构造方法的使用注意
- 子类中 我们一般不做父类继承过来的属性的初始化
- 子类只初始化自己特有的属性,及成果来的属性通过[super initWithXxx]来初始化父类继承过来的属性

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值