OC类与对象上半章节较为重要的部分

devtools/2024/10/21 10:04:34/

OC类与对象上半章节较为重要的部分

文章目录

  • OC类与对象上半章节较为重要的部分
    • 前言
    • OC对象的本质
    • OC的实例对象,类对象,元类对象
    • isa和superclass分析
    • 分析isKindOfClass和isMemberOfClass方法
    • ->和点语法的区别

前言

分享会的时候对于isKindOfClass和isMemberOfClass两者的区别不了解,所以写了这篇博客来记录上次的遗漏点。

OC对象的本质

首先我们都知道OC是一门面向对象语言编程,但是它是基于C\C++这两门语言实现的,所以OC的对象.类主要是基于结构体去实现的。

每当我们谈及OC对象的时候,我们就不得不说一下NSObject,所有的OC对象都继承自NSObject,上面也说了对象,类主要是基于结构体去实现的,那么这个结构体里到底有什么呢。

struct NSObject_IMPL {Class isa; //Class是一个结构体类型,isa是一个结构体指针
};
  • 继承自NSObject的对象结构大致是,这是一个继承自NSObject的对象Student(被添加了name和age两个属性)
struct Student_IMPL {struct NSObject_IMPL NSObject_IVARS;Class isa;)int _age;NSString *_name;
};
  • 即第一个元素是isa指针,我们可以认为isa的地址即是Student的地址,后面的成员变量会遵循内存对齐的原则逐一分配内存地址。

OC的实例对象,类对象,元类对象

OC主要包括了三种对象

  1. 实例对象
  2. 类对象
  3. 元类对象
  1. 实例对象就是通过类alloc出来的对象,每一次调用alloc都会产生一个新的instance对象。
  1. isa 指针
  2. 其他成员变量
@interface Student : NSObject
@property(nonatomic,strong)NSString * name;
@property(nonatomic,assign)int age;
@end

那么它就是如下的一个存储方式

请添加图片描述

  1. 类对象(class)

通过实例对象的class方法获取道这个实例的类对象,每个类在内存中有且只有一个class对象

  1. isa指针
  2. superclass指针
  3. 类的属性信息(@property)
  4. 类的对象方法信息(instance method)
  5. 类的协议信息(protocol)
  6. 类的成员变量信息(ivar)

他的内存信息是这样的
请添加图片描述

  1. 元类对象

笔者对于Runtime部分没有学习,但是记住每个类在内存中有且只有一个meta-class对象,

  1. isa指针
  2. superclass指针
  3. 类的类方法信息(class method)

isa和superclass分析

上面发现了一个事情就是实例对象内存里没有包含对象方法,实例对象怎么调用对象方法?类对象也没有类方法的信息,但是却可以通过类名调用类方法?子类如何调用父类的方法

  1. 实例对象的isa指向类对象
  2. 类对象的isa指向元类对象
  3. superclass指针只会存在类对象和元类对象中,每个类(元类)对象的superclass指针都是指向它的父类,

这里可以用一张非常经典的图片进行一个总结。

请添加图片描述

分析isKindOfClass和isMemberOfClass方法

当类调用 + (BOOL)isKindOfClass: (class)cls的时候,我们会从它的元类开始向上寻找,然后找他的元类的父类,知道找到根元类,然后在找到NSObject,

当元类调用+ (BOOL) isKindOfClass,同样是直接找到他的根元类,然后在找到他的根子类(NSObject).

当对象调用 - (BOOL) isKindOfClass:,这个函数则是从他的类开始向父类一直往上寻找直到找到NSObject为止。

而isMemberofClass函数则是仅仅包括了isKindOfClass函数的第一步,仅仅只比较isa指针是否指向后面的那一个元类或者是一个根元类这一个步骤。

总结isKindOfClass: (class)cls的几种情况

  • 类调用 + (BOOL)isKindOfClass: (class)cls

    • cls除了是[NSObject class]之外都报错
  • 元类调用的时候+ (BOOL)isKindOfClass: (class)cls

    • 判断cls是不是 根元类->NSObject 中的任意一个
  • 对象调用的时候则是判断

    • cls是不是 **类对象->父类->…->NSObject **(superclass继承链)其中一个

总结isMemeberOfClass:Class(cls)的几种情况

我们都是主要判断他的isa和cls相同

->和点语法的区别

  1. ->这个方式的访问是直接调用所指向的一个内存,这样子更快,而点语法实际上是调用他的setter语句和getter语句,这个语句调用的速度更慢
  2. 需要注意的是使用点语法访问属性的时候可以直接用“.”+属性名,而使用“->"访问属性的时候则不能省略成员变量名前的下划线“_”否则会报错。
  3. 我们一般不采用->的方式访问成员变量,但是成员变量默认受保护,所以常常报错。

self在类方法里指向的是(调用当前类方法的)类

self在对象方法中,self指的是对象。


http://www.ppmy.cn/devtools/32426.html

相关文章

根据前序遍历求树的各种遍历

//创建二叉树和三种遍历,输入序列如 1 5 8 0 0 0 6 0 0 #include <stdio.h> #include <iostream> using namespace std;struct Node{int data;Node* left;Node* right; };Node* create(void){int x;cin>>x;if(x0){return NULL;}Node *T new Node;T->dat…

Linux系统的source命令详解

目录 一、命令介绍 二、基本用法 三、使用场景 1、环境变量 2、函数和别名 3、配置文件 三、命令示例 1、一般的脚本文件 2、使用source的效果 四、使用 source 命令的重要性 1、修改当前 shell 会话的环境 2、加载配置文件 3、在当前 shell 会话中测试脚本 五、…

UDP 协议

UDP协议端格式 教科书上的&#xff1a; 16位UDP长度&#xff0c;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的最大长度&#xff0c;描述了这个数据报多长&#xff1b; 实际上的&#xff1a; UDP 会把载荷数据&#xff0c;就是通过 UDP Socket&#xff0c;即 sen…

个人对行为型设计模式的理解 @by_TWJ

目录 1. 访问者模式2. 迭代器模式3. 观察者模式4. 模板模式5. 状态模式6. 备忘录模式7. 策略模式8. 解释器模式9. 责任链模式10. 命令模式11. 中介者模式 研究了一下&#xff0c;我为了方便理解&#xff0c;对它们进行了分类&#xff1a; 针对请求者与执行者关系方面 1对多 - 责…

CocoaPods:iOS项目依赖管理的利器

CocoaPods&#xff1a;iOS项目依赖管理的利器 一、引言 在iOS项目的开发过程中&#xff0c;我们经常需要集成各种第三方库来快速实现某些功能&#xff0c;如网络请求、UI组件、数据处理等。然而&#xff0c;手动管理这些第三方库的版本、依赖和更新是一个繁琐且容易出错的过程…

Slave SQL线程与PXB FTWRL死锁问题分析

1. 问题背景 2.27号凌晨生产环境MySQL备库在执行备份期间出现因FLUSH TABLES WITH READ LOCK未释放导致备库复制延时拉大&#xff0c;慢日志内看持锁接近25分钟未释放。 版本&#xff1a; MySQL 5.7.21PXB 2.4.18 慢查询日志&#xff1a; 备份脚本中的备份命令&#xff1a;…

如何使用 Nginx 进行负载均衡

在这篇博客中&#xff0c;我们将详细介绍如何使用 Nginx 进行负载均衡。Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;它也经常被用作邮件代理服务器和通用 TCP/UDP 代理服务器。通过使用 Nginx 进行负载均衡&#xff0c;可以有效地分配客户端请求至多个服务器&…

让我们一起来领悟带环问题的核心思想

一、带环的链表&#xff1a; 本质还是快慢指针来解决 关于如下一个带环链表怎么去找到他们想碰到的节点呢&#xff1f;&#xff1f;&#xff1f;&#xff1f;我们可以想到快慢指针&#xff0c;第一个快点走&#xff0c;若是有环就会进入环&#xff0c;此时快指针每次走2步&am…