Skip to content

Objc Class&Object

Deepin edited this page Sep 1, 2021 · 1 revision

Q:对于objc这门语言,核心思想就是面向对象,那么何为对象呢?
A:女朋友?想多了,不过确实当初听过一个段子,单身么,new一个对象。这也算程序员的一种幽默了。

开篇

对于对象,按字面意思翻译是: object。在实际场景中,我们可能听到、看到或者表述的方式各异,不一定准确,下面我们先来看看oc中相关的词语有哪些:

  • 实例化对象(instance、id、object)、
  • 类对象(Class)、
  • 子类(subClass)、
  • 父类(superClass、也有叫超类的):
  • 根类(rootClass):
  • 元类(metaClass):
  • 根元类:
  • 分类(category)、
  • 扩展(extension)、
  • 变量(variable): 实例变量、成员变量、关联对象、
  • 属性(property): 私有属性、公有属性、只读属性、只读属性
  • 方法(method):
  • 协议(protocol)

对象、类、NSObject的关系

对象: 我们通常会说new(等同于alloc + init)一个对象,创建一个对象等,这些对象可能是属于UIKit框架中的:UIView类型的、UIButton类型、UILabel类型、UIViewController类型的,以及自定义控件类型的;也有可能直接创建一个NSObject类型的对象等等, 也就是说要有一个对象,首先得有一个类。

: 字面翻译就是:class. 但实际场景中,我们会用到如下的一些方法:

@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");

- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

去获取对象的父类,却没有用[Class new]或者[[Class all]init]的形式去创建过对象。

NSObject: 之前整理过关于NSObject信息, 里面包含了NSObject的头文件信息、源码、以及UI层面的继承关系图, 可以详细查看一下。不难发现,我们常用的控件,我们通常所谓的其实都源于NSObject

那么是不是可以说: 类就是NSObject呢?结论如何,我们通过objc的源码来分析验证。

Class、objc_class、objc_object

在xcode中打开一个任意一个objc项目,按下shift + command + O组合快捷键,

在"open quickly"搜索框中,输入objc.h, 敲下enter键,即可看到objc.h头文件的内容如下图:

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif

/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

可以看到Class是objc_class类型的结构体指针,id对象是objc_object类型的结构体指针,而objc_object结构体本身里面又有一个Class类型的isa,也就是Class与id都与objc_class有关.

相同的方法,再到"open quickly"搜索框中,输入runtime.h, 敲下enter键,即可看到runtime.h头文件的内容如下图(当前也可以直接在上一步objc.h文件上方路径处直接切换到runtime.h), 然后找到objc_class:

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

可以看出,objc_class也是一个结构体,这点和objc_object结构体类似,但objc_class相比于objc_object,除了共有的isa,还多出许多属性;

  - Class _Nullable super_class; - 父类
  - const char * _Nonnull name;  
  - long version;               
  - long info;                   
  - long instance_size;         
  - struct objc_ivar_list * _Nullable ivars;                     - 变量列表
  - struct objc_method_list * _Nullable * _Nullable methodLists; - 方法列表
  - struct objc_cache * _Nonnull cache;                          - 缓存
  - struct objc_protocol_list * _Nullable protocols;             - 协议列表

也就是说objc_object仅有一个isa,而objc_class除了isa,还有super_class

那么实例化对象(instance、id、object)、子类(subClass)、父类(superClass、也有叫超类的)、根类(rootClass)四者之间的关系可以如下图展示:

若是再把isa的指向关系考虑进去,就可以如下图来表示了:

NSObject

对于NSObject到底源于哪里,objc4中的NSObject.mm也是看不到的,可以参考详细信息

一般高级语言都是如下的关系: 机器语言--->汇编语言--->C\C++--->Objective-C

objc基于C\C++, 那么我们将objc转为c代码,即可查看NSObject的来源, 步骤如下:

  1. 在命令行cd到objc项目的main.m所在的目录
  2. 在命令行中执行其命令:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp
  3. 使用命令ls,在当前目录中可以查看到多了一个文件:main.cpp
  4. 执行命令open main.cpp,就可以打开该文件
  5. 全局搜索NSObject可以找到如下代码:
struct NSObject_IMPL {
    Class isa;
};

NSObject也是一个struct结构体,同objc_object一样拥有isa指针.

若还想深入了解,就得搞清楚struct结构体和isa了。

struct结构体

isa

1)分配空间 2)初始化 3)返回地址

Clone this wiki locally