-
Notifications
You must be signed in to change notification settings - Fork 0
Objc Class&Object
Q:对于objc这门语言,核心思想就是面向对象,那么何为对象呢?
A:女朋友?想多了,不过确实当初听过一个段子,单身么,new一个对象。这也算程序员的一种幽默了。
对于对象,按字面意思翻译是: object。在实际场景中,我们可能听到、看到或者表述的方式各异,不一定准确,下面我们先来看看oc中相关的词语有哪些:
- 实例化对象(instance、id、object)、
- 类对象(Class)、
- 子类(subClass)、
- 父类(superClass、也有叫超类的):
- 根类(rootClass):
- 元类(metaClass):
- 根元类:
- 分类(category)、
- 扩展(extension)、
- 变量(variable): 实例变量、成员变量、关联对象、
- 属性(property): 私有属性、公有属性、只读属性、只读属性
- 方法(method):
- 协议(protocol)
对象: 我们通常会说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的源码来分析验证。
在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的指向关系考虑进去,就可以如下图来表示了:
一般高级语言都是如下的关系:
机器语言
--->汇编语言
--->C\C++
--->Objective-C
objc基于C\C++, 那么我们将objc转为c代码,即可查看NSObject的来源, 步骤如下:
- 在命令行cd到objc项目的main.m所在的目录
- 在命令行中执行其命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp
- 使用命令
ls
,在当前目录中可以查看到多了一个文件:main.cpp
- 执行命令
open main.cpp
,就可以打开该文件
- 全局搜索
NSObject
可以找到如下代码:
struct NSObject_IMPL {
Class isa;
};
NSObject也是一个struct结构体,同objc_object一样拥有isa指针.
若还想深入了解,就得搞清楚
struct
结构体和isa
了。
1)分配空间 2)初始化 3)返回地址