id、构造方法、Category 分类、类的本质、description方法、SEL

1.id: 万能指针id :id对象不能用点语法、id对象本身已经有 * 了 因此变量名不能有 * 。
  可以吧id理解为 NSObject * 类型数据!

  int main()
    {
      @autoreleasepool {
        Person *p = [Person new];
        NSObject *o = [Person new];
        // 万能指针id
        id d = [Person new];
        [d setAge:10];
        [d setObj:@"123456"];
        NSLog(@"%d",[d age]);
    }
    return 0;
  }

2.构造方法:用于调用构造方法的同时初始化部分数据

  //Person.m :
  #import "Person.h"
  @implementation Person
  // 重写init方法
  - (id)init
  {
    if(self = [super init])
    {
      _age = 10;
    }
    return self;
  }
  @end

3.自定义构造方法:同时初始化更多数据

  //Person.m
  - (id)initWithName:(NSString *)name andAge:(int)age
  {
    if(self = [super init])
    {
      _name = name;
      _age = age;
    }
    return self;
  }

  //Student.m
  - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
  {
    if(self = [super initWithName:name andAge:age])
    {
      _no = no;
    }
    return self;
  }

4.Category-分类:在不改变原Person类的基础上给Person类扩展一些方法,主要用于给系统类扩展方法。

5.分类的应用:给系统类NSString类扩展一个方法

  //NSString+Number.m
  #import "NSString+Number.h"

  @implementation NSString (Number)
  // 分类的作用:可以扩展原类的功能。
  + (int)numberCountOfString:(NSString *)str
  {
    return str.numberCount;
  }
  - (int)numberCount
  {
    int count = 0;
    for (int i=0;i<self.length; i++) {
      unichar c = [self characterAtIndex:i];
      if (c >= '0' && c <= '9') {
        count++;
      }
    }
    return count;
  }
  @end

  //main.m
  #import <Foundation/Foundation.h>
  #import "NSString+Number.h"

  int main()
  {
    @autoreleasepool {
      int count = [@"s8dfdfs8df78sdf6s7" numberCount];
      NSLog(@"%d",count);
    }
    return 0;
  }

6.类的本质:

  1.当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法。只会调用一次。

  2.当第一次使用某个类时,就会调用当前类的+initialize方法

  3.先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法)
  先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的+initialize方法,最后调用的initialize方法的内容会覆盖前面所有initialize方法!)

7.description方法:

  NSLog(@"%@",c);语句执行前会:
  1.会调用类的+description方法
  2.拿到+description方法的返回值(NSString *)显示到屏幕上

  // 默认情况下,利用NSLog和%@输出对象时,结果是:<类名:内存地址>
    // 1.会调用对象p的-description方法
    // 2.拿到-description方法的返回值(NSString *)显示到屏幕上
    // 3.-description方法默认返回的是“类名+内存地址”

      // 输出行号
      NSLog(@"%d",__LINE__);
      // NSLog输出C语言字符串的时候,不能有中文
      // NSLog(@"%s", __FILE__);
      // 输出源文件的名称
      printf("%s "__FILE__);
      test9();
      Person *p = [[Person alloc] init];
      // 指针变量的地址
      NSLog(@"%p",&p);
      // 对象的地址
      NSLog(@"%p",p);
      // <类名:对象地址>
      NSLog(@"%@",p);

8.SEL:

  SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法

  其实消息就是SEL

    // 直接调用test2方法
      Person *p = [[Person alloc] init];
      [p test2];

    // 1.间接调用test2方法
      NSString *name = @"test2";
      SEL s = NSSelectorFromString(name);//将OC字符串转为SEL对象
      [p performSelector:s];//通过SEL对象间接调用方法test2

    // 2.间接调用test2方法
      [p performSelector:@selector(test2)];
      [p test3:@"123"];
      
      SEL ss = @selector(test3:);//将方法名test3转为SEL对象
      [p performSelector:ss withObject:@"456"];//通过SEL对象间接调用方法test3
      [p test2];
      
    // 1.把test2包装成SEL类型的数据
    // 2.根据SEL数据找到对应的方法地址
    // 3.根据方法地址调用对应的方法

原文地址:https://www.cnblogs.com/tzktzk1/p/3329615.html