# Day8--物件兄弟党的小弟们:属性与方法

在上一篇的文章中,有提到属性(property)这件事情指的就是类别或结构里面的所包含的变数、常数,而方法(method)就是类别、结构里面的函式。

而实质上,论及属性这件事情,有以下这四种的属性:

  1. 储存属性(stored property):在实体内储存常数或变数,可以用於类别及结构。
  2. 计算属性(computed property):在实体内计算一个值,可以用於类别、结构及列举。
  3. 型别属性(type property):与前两个不同,这是属於型别本身的属性。
  4. 属性观察器(property observer):用来观察属性值的变化,并以此触发一个自定义的操作。(资料来源:Swift起步走)

以下,将会分别描述这四种属性的特质:

属性

  1. 储存属性
    储存属性应该算是最简单的概念,它就是可以把值存进去里头,比较精准的说法应该是:储存在特定型别(类别或结构)的常数或变数。
    而作为用「储存」一词来形容,也就意味着可变;在一开始的时候,结构或类别的设定只给定所谓的预设值、型别,然而在过程中,是可以经过修改、储存等变动的。

如上述,在将Room404实体化後,我们便可以针对它的city这个项目来做一些内容性的更动。而这个时候打印出来的Room404的city就被改动了。
然而,上述的这个前提是建立在Room405的宣告是变数(variable)的情况,假若你今天宣称是常数(constant),那就等着报错吧,因为常数是无法更改的啊!:

  1. 计算属性
    计算属性的功用则是不存取值,而是以get、set两个关键字来存取值、或来设置其他属性的值
  • get:存取值
  • set:设置其他属性的值

如上述,get会做的事情就是让值被储存,所以可以看到右边列跑出了130,也就是被计算的值。

而set在做的事情则是设置其他属性的值,如上述,set( )中间传入了leveup,而在set内部则对HP内部进行了改变,也就是上升一个等级後,它就会增加它的血量,防御力也如是。(资料来源:Swift起步走、the swift programming language)

不过,关於100Days of Swift中所描述的计算属性则有一个不一样的例子:

总之,这个例子主要要谈的内容是,我们可以创造一个属性,这个属性里面可以有一些描述的计算,无论是if…else也好或whatever,它可以因此带入内部的其他属性进入这个属性里被使用,且因此从这个属性里输出这个属性的结果。

  1. 型别属性(type property)
    Swift起步走上对於型别属性的描述大概是这样:
    型别属性(type property)是属於这个型别(类别、结构或列举)的属性,无论生成了多少这个型别的实体,型别属性都只有唯一一份。
    型别属性使用於定义所有从这个型别生成的实体共享的资料。
    换句话说,就是型别属性是不变的,无论在有多少个化为实体,型别属性会是不变的。
    而型别属性如果是储存属性的话,则必须有预设值,如下的armysize = 0
    储存型的型别属性是延迟初始化的,只有在第一次被呼叫时才会被初始化,所以不需要对其使用lazy。
    而就以下的例子,「型别属性是使用static关键字作宣告变数或常数。」

总之,我们在产出了两个实体Tom & Leo後,我们的Armor就会自己对於其进行计算。

  1. 属性观察器
    属性观察器这件事情很有趣,它是一个具有时间性的东西,在Swift起步走上面的描述是这样:
    属性观察器(property observer)会监控和回应属性值的变化,每次属性被设置新的值都会呼叫属性观察器。
    而属性观察器的建构分别由以下二者:
  • willSet:在设置新的值之前呼叫,会将这个新的值当做一个常数参数传入,如果不命名这个参数名称时,会有一个内建的参数名称newValue。
  • didSet:在新的值被设置之後立即呼叫,会将旧的属性值当做参数传入,这个参数可以自己命名,或直接使用内建的参数名称oldValue。

总和上述,didSet的用途,其实主要是就是让新的属性能够被传进去参数里面,然後藉由值的传入去更动整个状态(我好像大概知道进度条要怎麽写了XD)
而willSet则是在所有事情发生前,会有一个值被当作类似默认的存在描述。
套用100 Days of Swift的例子:

总之,上面的程序码会打印出下面这个:

不过,据Paul Hudson认为:willSet是一个很少用的函式。
但不论如何,还是来试一下willSet:

总之,在这个案例中,hp是没有变化的,因为还没有叙述如何让血量减少的功能,或许往後会有机会尝试。

方法

继上述谈到所谓的属性後,可以了解struct、class中有属性也有方法,而方法这个东西,大致在概念上一分爲二:实体方法、型别方法

实体方法(instance method):先需要生成一个特定型别(类别、结构或列举)的实体,才能使用这个实体里的方法。
型别方法(type method):属於特定型别(类别、结构或列举)本身的方法。

  1. 实体方法
    实体方法需要做的事情,就是先在类别或结构里面详述方法内含什麽:

Mutating methods

100 Days of Swift-Mutating method的相关描述:

The problem is that when you create the struct Swift has no idea whether you will use it with constants or variables, so by default it takes the safe approach: Swift won’t let you write methods that change properties unless you specifically request it.

翻译翻译:当你创建 struct 时,Swift 不知道你是将它与常量还是变量一起使用,所以在默认情况下它将采用一个安全的方法:除非你特别要求,否则 Swift 不会让你编写改变属性的方法。

When you want to change a property inside a method, you need to mark it using the mutating keyword,

所以,当你需要改变一个方法里面的属性的时候,你需要标示”Mutating”

Swift起步走的相关描述:

一般情况下,一个值型别(结构或列举)实体的属性,不能在它的实体方法中被修改。但如果有特殊需求需要修改属性,可以使用变异(mutating)这个方法。要使用变异方法,将关键字mutating放在方法的func之前就可以了,如下:

我们在这边使用mutating func ,可以让原先的属性内容被改变
或许这里有更好的例子:

这边如果用mutating func的话,就会让someone的内容跟之前的预设去做改变,可能要体会一下。

  1. 型别方法
    形别方法有别於实体方法,为定义在特定型别(类别、结构与列举)上的方法,它不是属於实体,而是属於这个型别(类别、结构与列举)上的方法。
    什麽意思呢?
    可以这样说,就是class里面有class func ,所以它不是一种实体。

或是用static func来做也是可行的。

总之,型别方法不需要生成实体,就可以直接呼叫型别方法,因为型别方法是属於一个特定型别(类别、结构与列举),而非一个实体。

综合上述,我们讨论到三件事情,一是实体方法的使用,它必须经过实体话,才能以「实体.方法()」的方式来呼叫,而型别方法因为本身的构成是类别、结构里面含有型别方法,所以只要在外部将「类别.型别方法()」,拿出来使用就可以了。

而变异方法Mutating func则是在实体方法中,假若要在定义过的实体外部进行更动的话,就可以在类别、结构内部先设置一个变异方法,然後在外部套用,就会变成Mutating func所指定的内容。

tags: 铁人赛

<<:  AI ninja project [day 23] 生成对抗网路 Generative Adversarial Network(GAN)

>>:  JAVA 语言

企划实现(30)

止损 止损顾名思义就是停止损失,今天在做企划的同时,世界并不会停下来等你发展,所以如果在做企划的同时...

30天零负担轻松学会制作APP介面及设计【DAY 07】

大家好,我是YIYI,今天要开始用Whimsical画架构图了~ 进入Whimsical 先透过【D...

D10 第五周 (回忆篇)

这周原则上是复习周,没有太多课程进度,然後老师有提供一个线上挑战游戏,顺便让大家可以复习 API 相...

广播推送 - day24

目标 从左画面将讯息推送到右边画面,嗯! 就这样。 本示例从主画面推送讯息,其他开启本网的使用者无论...

[Day21] Tableau 轻松学 - Parameter

前言 有的时候我们会想让使用者输入一些参数,根据这些参数来做筛选或运算。到目前为止,我们没使用到这个...