开始进行Swift编程第6部分-结构,类,属性和方法

在上一篇文章中,我们介绍了函数,枚举和范围。

开始Swift编程第5部分-函数,枚举和作用域
在上一篇文章中,我们介绍了if语句,while循环和for-in循环(通常仅称为for循环)。 medium.com

它使我们对如何使用函数分解代码,使用枚举创建选项(并修复很长的if / else-if语句)的方式以及如何使内存使用率保持在较低水平并通过覆盖范围来查找讨厌的bug有了很好的理解。 。 今天,我们将讨论两个新对象,它们也是类型,它们也是容器,可帮助进一步分离代码并使代码更具可读性。 不要把代码分开得越多,就越容易阅读,这是一种快乐的媒介。 类和结构有助于建立这种媒介。 因此,让我们直接讨论一下Structs。

结构

C中的结构(如结构)是包含相似变量的数据类型,在Swift中,我们扩展了此功能,以允许结构也包含函数,枚举和其他结构,并且声明如下:

我们使用struct House声明一个结构,然后在主体中放入我们认为合适的任意数量的变量,常量或其他结构。 如果需要更改变量,请使用var声明它;如果不行,请使用let使其成为常量。

当我写出变量时,我会考虑应该测量或确定什么,然后通常以let开头并键入变量名称。 我问自己几个关于此变量应为哪种类型的问题。 这里只是几个问题:

  • 使用浮点数(双精度/浮点数)有意义吗?
  • 使用整数(Int)是否有意义?
  • 是否确定状态(布尔值/枚举)?
  • 它可以衡量或确定(结构)的多种因素吗?

问自己这样的问题将帮助您弄清楚要与特定变量一起使用的类型。 squareFootage可以用整数来度量,但也可以包含十进制数,因此我们将其默认为Double类型。 我们永远不能拥有一半的房间或四分之一的房间,因此numberOfRooms变成一个Int,与numberOfWindows相同。 您为什么认为我将numberOfBathrooms为Float。 我们永远不会有四分之一的浴室。 我们可以有一个完整的浴室,哦,等等,我们可以有一个半卫生间,其中只有一个水槽和一个厕所,或者一个水槽和一个浴缸。 因此,我们可以将1.5个半澡返回1.5 。 好的,那很有道理。 然后我们将address作为字符串常量。 为什么恒定? 好吧,如果您更改地址的时间为99.99999…%,那是因为您搬到了另一所房子,而这所房子不再适用于您,因此我认为将其设为常数是安全的。 然后我们有var doorIsOpen 。 好的,因此可以在两个可能的值之间切换,因此我们将其设为布尔值变量。

当然,我们可以在该结构中添加一个Garage ,因为我们都知道一个车库可以容纳这么多的汽车,因此我们可以说numberOfCars并将其numberOfCars Int 。 我们的车库可能有也可能没有窗户,因此我们允许设置窗户,但可以选择使用numberOfWindows: Int? 。 最后,如果我们要拉出车库或停在车库中,我们需要知道门是打开还是关闭。 我们使用doorIsOpen做到这doorIsOpen

呃,鲍勃…我们已经有了一个名为doorIsOpen的变量,它是基本House结构的一部分。 是的,我们这样做,但是由于范围doorIsOpenGarage结构中的doorIsOpen变量与House结构中的doorIsOpen变量不同。

让我们看看如何使用此结构来创建房屋。

如果您没有发现它,我们使用点运算符. 了解myHouse的不同元素。 如果需要从Garage结构读取变量,则可以通过房子访问车库。 myHouse.Garage.doorIsOpen 。 之前我说过,房屋和车库结构之间的门开度变量不相同,其原因是myHouse.doorIsOpenmyHouse.Garage.doorIsOpen不相同。

你说什么 您没有车库,那不是问题,除了嵌套结构,我们可以将它们分解并告诉房子可能有车库。

在这里,我们将Garage分解为它自己的结构,并在House结构中将其替换为变量(也许可以在房子上建一个),并将其设置为可选Garage?

如果您要一起订购,那么订购很重要。 如果要使用garage初始化myHouse ,则需要首先创建一个garage 。 或者因为garage是可选的,我们可以将其设置为nil,然后再创建一个newGarage并将其分配给myHouse变量,例如myHouse.garage = newGarage

班级

表面上的类与结构完全相同。 它们之间的皮肤深层差异很小,人们无法理解为什么您会选择其中一个。 每个人给您的原因是绝对的事实,这很简单, 类是引用类型,结构是值类型。 很简单吧? 您不高兴我们遍历了引用类型和值类型吗?

老实说,答案简单,但实际上答案复杂。 类通过引用传递。 结构按值类型传递。 让我们看看这在类和结构之间是如何工作的。

myHouse用作myHouse时发生了什么事? 这就是使用类的含义。 创建myHouse 实例时 ,我们在内存中给了它一个地址,作为对House的引用。 该地址引用了我们为House实例所需的所有信息。 创建yourHouse ,我们在内存中给了它一个不同的地址,其中包含您房子的所有信息。

这是棘手的部分。 当我们分配yourHouse = myHouse我们并不是说yourHouse 就像 myHouse ,而是说yourHouse myHouse ,方法是将它指向myHouse所引用的内存中的地址。 因此,当您关闭yourHouse的门时,您实际上就关闭了myHouse的门。 您将yourHouse分配给yourHouse之后不久,存储在yourHouse的信息yourHouse被删除。

现在,当我们使用结构进行完全相同的操作时,我们将值存储在变量中。 当我们分配yourHouseStruct = myHouseStruct我们可能已经将Integer变量从一个数字更改为另一个数字。 这是它的整洁部分。 结构是写时复制的。 这意味着当我们说yourHouseStruct = myHouseStruct ,系统实际上引用了myHouseStruct信息所在的内存位置。 您可以像yourHouseStruct = myHouseStruct = myHouseStructInfo一样关注它。 我们一关上yourHouseStruct的门, yourHouseStruct在内存中的其他位置myHouseStruct yourHouseStruct的副本, myHouseStructyourHouseStruct分配了新的内存。

一个类也可以从其他类继承 。 这意味着,任何继承另一个类的类都具有自己的变量和函数,但也采用超类或其继承的类中的变量和函数。 让我们看看它是如何工作的。

在这里,我们有一个名为Ball的类,它定义了sizebouncinesscolorSoccerBall使用语法SoccerBall: BallBall继承。 这意味着SoccerBall实例SoccerBall将包含secondaryColor而且还将包含size, bouncinesscolor 。 由于BaseballSoccerBall我们不想让BaseballSoccerBall继承,但这是Ball的一种,因此我们可以再次从超类Ball继承来获取Ball中包含的变量。 除了现在,我们有threadColor直接来自BaseBall类。

对此进行另一种观察的方式就像在科学中一样,我们将生物分类为王国,s,纲,阶,科,属和种。 在生物的高等分类中,所有正确的事物一直到种属都是正确的,但是,仅在低等分类中可用的事物,在高等分类中不可用。

方法和性质

我敢打赌,您很高兴看到我完成了这一节的全部内容,我敢打赌,您也很高兴知道这一节很短。 但是我现在要告诉你

我一直在骗你。

没错,因为我想向您解释方法和属性非常糟糕,所以我不希望向您介绍这些名称,除非您对类和结构有所了解。

当在类或结构中使用方法时,方法只是函数的另一个名称。 全名是instance method,因为它们属于类或struct的实例,但是我们仅将它们简称为方法。 我上面没有使用任何方法,但以前在其他文章中也曾使用过。 当我使用语法var arrayCount = someArray.count ,数组类型具有一个称为count的内置方法,其唯一目的是对Array中的元素进行计数,因此当我们说someArray.count我们只是访问了Array类型的count方法。 count方法返回Int值,因此根据类型推断规则, arrayCount是Integer类型。

属性只是属于类或结构实例的变量或常量的别称。 有HouseBall甚至SoccerBall

说到我没有在类实例中使用方法这一事实,现在让我们开始讨论新的事物,然后我们就可以完成了。

在这里,我们访问myHouse的方法。 通过使用点运算符并调用函数toggleDoor() ,我们可以根据门的当前状态打开或关闭门。 我们可以在切换门之前检查门的状态,以确保通过使用来打开或关闭门
if myHouse.isDoorOpen { myHouse.toggleDoor() }
仅在门打开时才关闭门。

本节的最后一部分,就是self关键字。 self引用此对象的实例。 当我们说self.isDoorOpen我们指的是myHouse.isDoorOpen但是我们使用它是因为在使用它的时候,我们不知道变量名是什么。 可能是你的yourHouse或他们的theirHouse 。 使用self可以使我们为类或结构的所有实例提供此功能,而不必担心语法是否正确。

摘要

我们了解了结构和类,它们如何相同以及如何不同。 关于类和结构还有更多的知识,但是在Swift中,首先使用Struct,然后仅在需要类提供的额外功能时才移至类。 执行此操作时,只需要在开始时将struct更改为class 。 就这么简单。

我们还了解到,我是个糟糕的骗子,我写了整篇文章,说变量和函数而不是属性和函数。 (这实际上确实很难做到,而我的删除密钥将在这一点上为我担保)。 只需记住,在类或结构内部的变量称为属性,而在类或结构内部的函数称为方法。 不用担心滑倒,不会因此而停靠,还有其他更重要的事情要担心,例如向老板解释方法的用途以及为什么选择将这种类型的属性用于其他属性。

下一步是什么

我们将继续讨论类和结构,但将讨论初始化和反初始化,覆盖和引用计数。 在此之前,请尝试考虑程序中可能是类或结构的事物。 考虑一下它们可能拥有哪些属性和方法。

开始进行Swift编程第7部分-初始化和反初始化,覆盖和…
在上一篇文章中,我们讨论了结构,类,属性和方法。 它帮助我们弄清楚了我们该怎么做…… medium.com