【OC】面向对象基础与Foundation框架总结


前言

笔者花了三周的时间学完了OC的一些基础知识,特此写下这篇博客来总结与运用学到的知识。

一、面向对象

1、类与对象

类与对象是我们面向对象程序设计语言中非常重要的一部分。我们通过我们的类来创建我们的对象。 我们创建我们的类的步骤分为两个部分:接口与实现部分。 接口用于定义我们的方法与成员变量,我们也可以使用@property来定义我们的属性 实现部分则为我们的方法提供实现

2、创建并使用对象

然后我们就开始创建并使用我们的对象。 接下来我们举例一个对象的创建: FKUser *a = [[FKUser alloc] init];

其中a是我们的变量名,FKUser是我们的类,alloc为我们创建的对象在堆内存中分配空间。
这里我们需要着重理解我们的alloc,当我们使用alloc时实际上是调用allocWithZone,这个在后面使用单例模式的时候会使用到。
然后就是如何调用我们的方法:我们调用方法的方式遵循我们日常说话的逻辑:主谓宾。
我们的主语是我们的类或对象,谓语是我们的方法,宾语就是我们传入的参数。
例如蔡徐坤打篮球:蔡徐坤就是对象,打就是方法,篮球就是参数,有时候我们的方法可能不需要传参,那么此时我们就没有我们的宾语了

3、单例模式

接下来就是我们比较重要的单例模式了,我们的单例模式其实也可以称作单例类模式,他是一个类方法,具体作用后面会继续学习并写博客总结,在这里先抛出一个问题:为何两种方式创建的单例变量的地址不同?
后面在笔者学习的过程中会逐步解决这个问题并完善单例模式:
实现部分:
在这里插入图片描述
函数部分:
在这里插入图片描述
这里的输出为0

4、隐藏与封装

接下来到了我们的隐藏与封装部分。这里我们比较重要的主要是我们的几种访问控制符与我们的@property,在这里必须强调一下我们的属性就是我们的成员变量。然后我们比较需要着重记住的就是我们的protect访问控制符是允许我们的成员变量在本类及其子类中访问,我们在接口部分定义我们的成员变量时会默认使用我们的protect。
然后还有一点就是当我们使用我们的点语法时,我们的点语法是访问类的属性,本质是调用我们的set与get方法。我们的 -> 默认是访问我们的成员变量,但是我们的成员变量常常受保护,所以常常会出现报错。

5、对象初始化

然后我们接下来对我们的对象进行初始化操作。本来我们的init方法是将我们的对象的成员变量设为初值,但是我们也可以重写我们的init方法,来减少我们的代码复用。
这里给出我们的对象初始化的模版:
在这里插入图片描述
这里笔者来解释一下self = [super init]
在此之前我们需要解释我们的self关键字 :self关键字总是指向调用该方法的对象self关键字的最大作用是让类中的一个方法访问该类的另一个方法与成员变量。由此可以理解我们的self关键字一般是在实现部分使用。还有一点就是我们的self关键字只能调用我们的实例方法
我们的代码的意思就是如果我们的对象创建成功,那么我们就对这个对象赋予初值。

6、继承

接下来到了我们的继承部分:
我们的继承部分的特点是我们的子类会继承我们父类暴露出来的成员变量与方法,同时我们的子类也可以重写我们的父类的方法
我们的super关键字就是让我们的子类的方法重写后可以调用我们父类中的方法

7、多态

类的多态的关键主要是我们的程序分为编译阶段与运行阶段,变量的类型就是我们编译阶段的类型,我们的为对象分配的空间的类就是我们运行阶段的类型。我们只能调用我们编译阶段的类所具有的方法,但是最后调用的一定是运行阶段的类的方法。我们还要记得我们不能调用运行阶段的类具有但是编译阶段没有的方法

扫描二维码关注公众号,回复: 15853662 查看本文章

就下来我们来到我们面向对象的下篇

8、包装类与处理对象

首先我们学习的是包装类与处理对象,我们知道oc是面向对象的编程语言,但他也是由c语言扩展而来的。但是我们c语言中的基本类型不是对象,例如int,double之类的。他们没有对象的特征,他们那也没有属性方法可以调用
我们的NSNumber与我们的NSValue都是我们的包装类,他们可以把我们的基础类型的数据添加到我们的NSArray集合中,因为我们的oc要求我们集合中的元素一定要是对象
我们将我们的基础类型包装成对象时,通俗的方法是用我们的类方法直接将我们的特定类型的值包装成NSNumber
这些方法的关键都是调用我们的类方法将基本类型包装成对象来将其加入到集合中

9、重写description方法

我们将我们的值包装成对象后我们肯定就需要打印他了。当我们用NSLog单独打印我们的对象时,实际上是调用我们的description方法来返回我们的类的十六位进制,但是我们并不想要得到这个东西,我们想要得到的是他的值,所以我们就要重写我们的description方法。

10、==与isEqual

= = 与isEqual方法也是我们oc学习中的重点。
我们的==只有在我们的两个变量的地址相同时才会返回真,而我们的isEqual是一个实例方法,所有的指针变量都可以调用这个方法来判断是否与其他指针变量相等。
但是我们需要注意我们的NSObject中的isEqual实际上与 = = 没有区别,但我们的NSString类中重写了这个方法,他的标准是只要两个字符串的字符序列相同就会返回真。
还有一点便是我们的oc为了节约我们的内存,当创建两个完全相同的实例变量时,会将这两个指针变量指向同一个对象。

11、类别与扩展

接下来学习的路线就到了我们的类别与扩展
我们的类别可以保证我们动态地为我们现有的类添加新方法,而不用访问父类的源代码或是创建子类。我们一般是在类别的h文件中定义模块化的方法,并在m文件中实现。
但我们的扩展就仅仅只是用来定义我们的方法,方法的实现部分会在类中实现。

12、协议与委托

然后就到了比较重要的协议与委托
我们可以用我们的类别来模拟我们的协议,笔者在这里重点讲一下我们的正式协议。
我们的协议与我们的类一样,可以相互继承,同时我们的协议中只能定义方法,不用提供方法实现。
但我们这里需要注意我们的协议的继承格式
在这里插入图片描述
我们要在我们类的接口部分加上我们的类需要继承的类,一般选择NSObject,然后后面跟着我们需要其实现的协议。
我们还用两个关键字来判断我们的方法是必须实现还是选择实现
@required是必须实现
@optional是选择实现

二、Foundation框架

我们这里主要讲一下一些框架中包含的类,例如NSString,NSDate与集合类等。

1、NSString类

我们对一个NSString对象赋值的方法是直接将字符串常量赋给对象,例如:NSString *str = @"hello";
因为我们的NSString是不可变的,所以我们只能通过一些方法来在我们原来的字符串后面追加或初始化我们的字符串来间接修改我们的对象,例如:
在这里插入图片描述
这两个方法都是对象不改变,将新生成的字符串重新赋给str指针变量

2、NSMutableString类

我们的这个类与上面的类不同,他的字符序列是可以改变的,我们通过一些个方法对其进行使用
在这里插入图片描述
在这里我们可以注意一下我们的的可变与不可变的区别:我们对我们的NSString对象进行赋值时,必须要将调用后的方法返回的值重新赋给我们的对象,例如a = [a stringByAppendingString:@"iii"];,而我们的NSMutableString就不用重新赋值,可以直接修改。 两个类方法的不同就是一个有stringby前缀,另一个没有。

3、日期与时间

OC为处理这些提供了NSDate,NSCalendar对象。
先来介绍我们的NSDate:
在这里插入图片描述

4、日期格式器

我们的日期格式器分为类中的与自定义的格式器
在这里插入图片描述

5、定时器

定时器笔者这里还没理解,后面理解了会添加上来

6、对象复制

我们的对象复制也分为copy与MutableCopy方法,copy方法返回的是一个不可变的字符串,mutable返回的是一个可变的字符串,然后我们得到我们的副本后对其进行修改对原来的没有任何影响。
例子:
在这里插入图片描述
这里可以看到我们复制的对象是可以被修改的。但是我们自创建的类是无法调用这个方法的,我们必须重写我们的copyWithZone方法我们才能成功复制我们的对象。

当我们调用对象的copy方法来来复制自身时,我们的程序底层实际上是调用copyWithXxxx:方法来完成实际的复制工作。copy返回的实际上就是copyWithXxxx:方法的返回值。mutableCopyWithZone也相同。

深复制与浅复制是我们比较重点的一个内容,我们的这里回顾一下浅复制的定义:当一个对象的成员变量是指针变量时,如果该程序只是复制该指针的地址,而不是真正复制指针所指向的对象,那么这种方式被称为浅复制。
也就是说,我们对自定义的类进行copyWithZone方法进行重写时,不是真正的进行了深复制,因为类似复制对象的NSString型成员变量与被复制变量的实际指向对象相同

我们这里的解决办法是递归复制每个指针类型的成员变量
在这里插入图片描述

这里我们来浅讲一下我们的copy属性,实际上他的作用就是在我们使用set方法对我们成员变量进行赋值时,我们的程序就会调用copy方法,将复制的不可变副本传给我们的对象来避免非法修改

7、array

这里我们需要着重记忆的是我们向数组类传参的方法一般用arrayWithObjects:
然后我们看一下如何遍历我们集合类中的元素,这里介绍两种方法,比较常用的是for…in方法,是第一种
在这里插入图片描述
注意我们这里的obj是我们的xiyoumobileperson,这是一个对象,我们要获取的是他里面的iOS属性的值。

对于可变数组的方法我们直接给出他的调用:
在这里插入图片描述

8、set

我们看我们的集合,我们向集合中添加元素的方法是:setWithObjects:

我们在使用set是需要注意的是我们一般会对我们hash方法进行重写,因为我们集合中判断两个元素相等的标准是:方法isEqual返回yes与两个对象的hash方法返回值也相等,set才会判断这两个对象相等。我们重写我们的hash方法一般用如下代码:
在这里插入图片描述

9、dictionary

我们可以把我们的字典想象成我们的链表。他有key与value,这二者具有映射关系,我们通过我们的key来查找我们的value。
在这里插入图片描述
我们这里看到我们的字典的value中存放的不一定是基本类型变量,也可以是其他自定义的类

这里就引出笔者的先前碰到的一个问题:
定义了一个model类,他的子类是xiyoumobileperson
在这里插入图片描述
给出xiyoumobileperson类,里面有一些成员变量
在这里插入图片描述
因为我们model类中有一个属性是mutablearray,所以我们可以创建一个model类对象并用点语法对里面的可变数组属性添加对象,注意我们这里的对象不一定是我们的基本类型,也可以是我们的自定义类,就像我们上述字典中的value一样

在这里插入图片描述

假如我们像上面向数组中添加了自定义类,那么我们可以通过调用方法来访问自定义类中的对象,这里要注意我们在向数组中添加元素之前,我们一定需要先创建一个自定义类对象,然后利用arrayWithObjects:方法将我们的对象加入array中

这里我们再提一下我们的遍历数组的方法:
在这里插入图片描述
我们的array与我们的c语言一样具有下标,如果我们要遍历元素,要么先找到我们下标对应的对象,要么就使用我们的for…in方法
这里还要注意如果我们数组中的元素是一个自定义类,那么获取自定义类的成员变量一定要调用我们的方法

猜你喜欢

转载自blog.csdn.net/weixin_72437555/article/details/130545526