This is the third day of my participation in Gwen Challenge

preface

First of all, I will talk about the relationship between class and object. Class and object are the collective names of two kinds of computer languages based on computers. Objects are abstractions of objective things, and classes are abstractions of objects. A class is an abstract data type. Simply put, a class is a defined type, and an object is something that comes out of new or alloc&init. So what is an object in Objective-C and how do you implement it? As we all know, Objective-C evolved from C++, so it’s not hard to guess that there are only two C++ classes or constructs that can be implemented. Now let’s use Clang to see how classes are implemented in Objective-C.

Implementation of OC objects

For convenience, I created a new MacOS command-line project and changed my main.m to main.mm to compare C++ and Objective-C classes.

Main. mm file code:

#import <Foundation/Foundation.h> class LQPeople { private: int a; protected: int b`; ` public: int c; }; @interface LQTest : NSObject @property(nonatomic,copy)NSString *name; @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!" ); } return 0; }Copy the code

Use the clang command

clang -rewrite-objc main.mm -o main.cpp

Get our mian. CPP file and open the CPP file to search our LQTest.

foundLQTestIt’s one of the two hypotheses, it’s the structure, but there’s something vaguely wrong with ournameGo to which? Turned out to beLQTestHas not been realized…

One more time…

Main. mm file code:

#import <Foundation/Foundation.h> class LQPeople { private: int a; protected: int b; public: int c; }; @interface LQTest : NSObject @property(nonatomic,copy)NSString *name; @end @implementation LQTest @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!" ); } return 0; }Copy the code

Use the clang command

clang -rewrite-objc main.mm -o main.cpp

Get our mian. CPP file and open CPP to view it.

There you go. OurLQTestIt turns into a structure and comes to a conclusionOC classes are struct implementations, and the objects we create are actually structures.

summary

  1. OC classes are struct implementations, and the objects we create are actually structures.
  2. The OC class is not implemented and only generates a structure identifier.

The nature of OC objects

Now that we know that OC objects are essentially structures, let’s explore how objects are implemented. What is the nature of the object? What does the property become? What’s the method going to be?

attribute

Code first:

@interface LQTest : NSObject @property(nonatomic,assign)int i; @property(nonatomic,assign)char c; @property(nonatomic,assign)bool b; @property(nonatomic,strong)NSString *name; @property(nonatomic,strong)NSData *data; @property(nonatomic,strong)NSDate *date; @end @implementation LQTest -(void)test { } @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!" ); } return 0; }Copy the code

Use the clang command

clang -rewrite-objc main.mm -o main.cpp

Get our mian. CPP file and open it up.

Class isa pointer to objc_class. When I tried to find objc_class, I found only one definition. The implementation is not there. I won’t go into this for the time being, but I’ll study it later.

struct NSObject_IMPL {
	Class isa;
};

typedef struct objc_class *Class;
Copy the code

The underlying member variables still hold char, bool, int. But NSString, NSData, and NSDate are not NSString, NSData, and NSDate in our OC. It’s all structure objc_Object. Objc_object has only one isa pointer of Class type in it.

// @class NSString;
#ifndef _REWRITER_typedef_NSString
#define _REWRITER_typedef_NSString
typedef struct objc_object NSString;
typedef struct {} _objc_exc_NSString;
#endif

// @class NSData;
#ifndef _REWRITER_typedef_NSData
#define _REWRITER_typedef_NSData
typedef struct objc_object NSData;
typedef struct {} _objc_exc_NSData;
#endif

// @class NSDate;
#ifndef _REWRITER_typedef_NSDate
#define _REWRITER_typedef_NSDate
typedef struct objc_object NSDate;
typedef struct {} _objc_exc_NSDate;
#endif

struct objc_object {
    Class _Nonnull isa __attribute__((deprecated));
};
Copy the code

methods

We don’t see the method we defined in the structure definition. Where did the defined methods go? Let’s keep looking.

static struct /*_method_list_t*/ {
	unsigned int entsize;  // sizeof(struct _objc_method)
	unsigned int method_count;
	struct _objc_method method_list[25];
} _OBJC_$_INSTANCE_METHODS_LQTest __attribute__ ((used, section ("__DATA,__objc_const"))) = {
	sizeof(_objc_method),
	25,
	{{(struct objc_selector *)"test", "v16@0:8", (void *)_I_LQTest_test},
	{(struct objc_selector *)"i", "i16@0:8", (void *)_I_LQTest_i},
	{(struct objc_selector *)"setI:", "v20@0:8i16", (void *)_I_LQTest_setI_},
	{(struct objc_selector *)"c", "c16@0:8", (void *)_I_LQTest_c},
	{(struct objc_selector *)"setC:", "v20@0:8c16", (void *)_I_LQTest_setC_},
	{(struct objc_selector *)"b", "B16@0:8", (void *)_I_LQTest_b},
	{(struct objc_selector *)"setB:", "v20@0:8B16", (void *)_I_LQTest_setB_},
	{(struct objc_selector *)"name", "@16@0:8", (void *)_I_LQTest_name},
	{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_LQTest_setName_},
	{(struct objc_selector *)"data", "@16@0:8", (void *)_I_LQTest_data},
	{(struct objc_selector *)"setData:", "v24@0:8@16", (void *)_I_LQTest_setData_},
	{(struct objc_selector *)"date", "@16@0:8", (void *)_I_LQTest_date},
	{(struct objc_selector *)"setDate:", "v24@0:8@16", (void *)_I_LQTest_setDate_},
	{(struct objc_selector *)"i", "i16@0:8", (void *)_I_LQTest_i},
	{(struct objc_selector *)"setI:", "v20@0:8i16", (void *)_I_LQTest_setI_},
	{(struct objc_selector *)"c", "c16@0:8", (void *)_I_LQTest_c},
	{(struct objc_selector *)"setC:", "v20@0:8c16", (void *)_I_LQTest_setC_},
	{(struct objc_selector *)"b", "B16@0:8", (void *)_I_LQTest_b},
	{(struct objc_selector *)"setB:", "v20@0:8B16", (void *)_I_LQTest_setB_},
	{(struct objc_selector *)"name", "@16@0:8", (void *)_I_LQTest_name},
	{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_LQTest_setName_},
	{(struct objc_selector *)"data", "@16@0:8", (void *)_I_LQTest_data},
	{(struct objc_selector *)"setData:", "v24@0:8@16", (void *)_I_LQTest_setData_},
	{(struct objc_selector *)"date", "@16@0:8", (void *)_I_LQTest_date},
	{(struct objc_selector *)"setDate:", "v24@0:8@16", (void *)_I_LQTest_setDate_}}
};

// @implementation LQTest

static void _I_LQTest_test(LQTest * self, SEL _cmd) {
}

static int _I_LQTest_i(LQTest * self, SEL _cmd) { return (*(int *)((char *)self + OBJC_IVAR_$_LQTest$_i)); }
static void _I_LQTest_setI_(LQTest * self, SEL _cmd, int i) { (*(int *)((char *)self + OBJC_IVAR_$_LQTest$_i)) = i; }

static char _I_LQTest_c(LQTest * self, SEL _cmd) { return (*(char *)((char *)self + OBJC_IVAR_$_LQTest$_c)); }
static void _I_LQTest_setC_(LQTest * self, SEL _cmd, char c) { (*(char *)((char *)self + OBJC_IVAR_$_LQTest$_c)) = c; }

static bool _I_LQTest_b(LQTest * self, SEL _cmd) { return (*(bool *)((char *)self + OBJC_IVAR_$_LQTest$_b)); }
static void _I_LQTest_setB_(LQTest * self, SEL _cmd, bool b) { (*(bool *)((char *)self + OBJC_IVAR_$_LQTest$_b)) = b; }

static NSString * _I_LQTest_name(LQTest * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LQTest$_name)); }
static void _I_LQTest_setName_(LQTest * self, SEL _cmd, NSString *name) { (*(NSString **)((char *)self + OBJC_IVAR_$_LQTest$_name)) = name; }

static NSData * _I_LQTest_data(LQTest * self, SEL _cmd) { return (*(NSData **)((char *)self + OBJC_IVAR_$_LQTest$_data)); }
static void _I_LQTest_setData_(LQTest * self, SEL _cmd, NSData *data) { (*(NSData **)((char *)self + OBJC_IVAR_$_LQTest$_data)) = data; }

static NSDate * _I_LQTest_date(LQTest * self, SEL _cmd) { return (*(NSDate **)((char *)self + OBJC_IVAR_$_LQTest$_date)); }
static void _I_LQTest_setDate_(LQTest * self, SEL _cmd, NSDate *date) { (*(NSDate **)((char *)self + OBJC_IVAR_$_LQTest$_date)) = date; }
// @end
Copy the code

We can see that our methods have all become static c++ functions, with an _method_list_t to map them.

conclusion

1. OC objects are structures by nature.

2. The base member variables of the OC object remain as base member variables, but the member variables of the class type are converted to structure Pointers.

3. OC object class methods are implemented by static functions, and thenmethod_listMapping, the specific call is just passing in parameters.

4 in-depth understanding also need to refer to the source code.