//
//  main.m
//  Objc4_Study
//
//  Created by huangyirong on 2020/5/21.
//  Copyright © 2020 Sogou. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

///OC对象分类
///instance对象、class对象、meta-class对象
///
///
///实例对象
///实例对象就是通过类alloc出来的对象，每次调用alloc都会产生新的实例对象，都会分配新的存储空间
///实例对象在内存中存储的信息包括isa和其他成员变量
///几乎所有实例对象都有isa，因为都是继承NSObject
///
///2、每一个实例对象都有isa，而且在该内存地址的最前面，也就是例如Student *stu = [[Student alloc] init]; 如果isa的地址是0x30020 所以stu指针存储的地址值也就是0x30020，指向这个Student实例对象
///实例对象没有存储方法，为什么？不可能每个alloc出来的对象都需要一份方法列表太浪费存储在对应的class中
///
///
///2、通过对一个实例对象内存结构的理解，有助于研究其他问题，如分析一个对象分配多少内存
///
///class_getInstanceSize()
/// 传入一个类，返回这个类最终创建出来的实例至少需要多少存储空间
///class_getInstanceSize([Student class])
///
///
///malloc_size() 传入指针，返回指针所指向内存大小，其实也是实际分配的大小，存在内存对齐问题，iOS系统中buket size，分成好多段，16、32，128字节等等 nano size什么的
///malloc_size((__bridge const void *)(stu))
///
///
///sizeof() 实际上是运算符（不是函数），传的是类型，比如int、float、struct或者指针，返回这个类型有多大，一编译就转成常数，类似宏,sizeof(double) ，转成汇编看实际上就是常数8，sizeof(stu) stu是指针变量则为8个字节,sizeof(struct)也为8
///
///
///笔记-其他注意点
///alloc 调用
///_objc_rootAllocWithZone
///class_createInstance
///calloc
///alignxxxx
///
///

///
///meta-class元类对象
///meta-class可以理解成用来描述类的
///

struct NSObjct_IMPL {
    Class isa;
};

struct Person_IMPL {
    struct NSObjct_IMPL NSObjct_IVARS;
    NSString *name;
    int age;
};

struct Student_IMPL {
    struct Person_IMPL NSObjct_IVARS;
    NSString *name;
    int age;
    int number;
};

@interface Person : NSObject
{
    NSString *name;
    int age;
}
- (void)say;
+ (void)fuxx;

@end

@implementation Person

- (void)say
{
    
}
+ (void)fuxx
{
    
}

@end

@interface Student : Person
{
    int number;
}
- (void)study;
@end

@implementation Student
- (void)study
{
    
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
//        NSLog(@"Hello, World!");
        
        ///类对象示例代码
        Student *stu = [[Student alloc] init];
        ///类对象获取方式
        Class objClass1 = [stu class];
        Class objClass2 = [Student class];
        Class objClass3 = object_getClass(stu);
//        NSLog(@"1:%p 2:%p 3:%p",objClass1,objClass2,objClass3);
        [stu study];
   ///类对象 ///每个类再内存中有且只有一个class对象，因此objClass1、objClass2和objClass3指向的地址都是一样
        ///类对象再内存中存储的信息主要包括
        ///isa指针
        ///superclass指针
        ///类的属性信息（@property）、类的对象方法信息（instance method）
        ///类的协议信息（protocl）、类的成员变量信息（ivar）
        ///
        ///注意，类对象包含的成员变量信息并非比如Person的成员变量name的值是多少
      ///成员变量的值是由实例对象决定的，这里类对象的成员变量信息主要是这个变量的名称、类型等描述信息，只需要存储一份，不管对于哪个实例对象这些信息都是固定不变
        ///
        ///
        ///获取元类对象
        Class objectMetaClass = object_getClass([Student class]);
        ///object_getClass传入的是类对象，获得元类对象
        ///
        Class objectMetaClass2 = [objClass2 class];
        ///objectMetaClass2返回的也是元类对象吗？
        ///可以通过以下runtime api判断
        class_isMetaClass(objectMetaClass2);
        ///不是。。试了下类对象无论调用多少次class方法始终返回类对象
        ///
        ///每个类在内存有且只有一个meta-class对象
        ///meta-class对象和class对象的内存结构是一样的（类对象和元类对象指针类型都是Class，所以指向内存的结构一样），但是用途不同，
        ///在内存中存储的主要信息包括
        ///isa指针
        ///superclass指针
        ///class method类的类方法信息
        ///
        ///比起class对象包含的东西好像少了，内存结构还能一样？
        ///meta-class中那些属性信息、协议信息等等都为null
        ///两者类型一样指向的都是typedef struct objc_class *Class结构体
        ///
      
        ///
        ///思考
        ///1、对象的isa指针指向哪里？
        ///
        ///instance的isa指向class
        ///class的isa指向meta-class
        ///meta-class的isa指向基类的meta-class
        ///
        ///
        ///2、OC的类信息存在哪里？
        ///
        ///
        ///
        ///
        ///3、object_getClass() vs objc_getClass()，内部实现
        ///
        ///Class objc_getClass(const char *aClassName) （源码在objc-runtime.mm里）
        ///传入字符串类名，返回对应的类对象
        ///
        ///Class object_getClass(id obj) (编码在objc-class.mm里)
        ///传入的obj可能是instance对象（返回class对象）
        ///class对象(返回meta-class对象)
        ///meta-class对象（返回NSObjectd meta-class对象）
        ///
        ///-（Class）class; 返回类对象
        ///
        ///
        ///xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
        ///-framework链接上其他框架 如 -framework UIKit
        ///
        ///搜 int main(int argc, const char * argv[])
        ///
        ///[stu study];
        ///
        ///objc_msgSend(stu,@selector(study))
        ///stu对象发送一条消息@selector(study)
        ///stu需要先找到实例方法才能调用成功，怎么找到？
        ///通过isa找到对应类对象，再找到实例方法
        ///同样道理，类对象调用类方法，也是类对象通过isa找到元类对象中的类方法实现
        ///
        ///总结下
        ///instance的isa指向class，当调用对象方法时，通过instance的isa找到class
        ///最后找到对象方法的实现进行调用
        ///class的isa指向meta-class，当调用类方法时，通过class的isa找到meta-class
        ///最后找到类方法的实现进行调用
        ///
        ///
        ///
        ///关于superclass指针
        ///
        ///先看class对象中的superclass指针
        ///Student的类对象的superclass 指向 Person的类对象，后者的superclass指针指向 NSObject的类对象
        ///也就是类对象的superclass指向它父类的类对象
        ///
        ///[stu say];、[stu init];调用过程？
        ///当Student的instance对象调用Person的对象方法时，
        ///会先通过isa找到Student的class，
        ///然后通过superclass找到Person的class，最后找到对象方法的实现进行调用
        ///
        ///同理，元类对象的superclass指针指向它的父类的元类对象
        ///[Student fuxx]; 、[Student load];
        ///当Student的class要调用Person的类方法时，
        ///会先通过isa找到Student的meta-class,
        ///然后通过superclass找到Person的meta-class，
        ///最后找到类方法的实现进行调用
        ///
        ///总结
        ///class的superclass指向父类的类对象
        ///meta-class的superclass指向父类的meta-class对象
        ///基类的meta-class的superclass指向基类的class（特殊）
        ///
        ///
        ///instance对象调用对象方法的流程
        ///

        

        
        
        
        
        
        
        

    }
    return 0;
}
