Swift基础-类和继承

创建自己的类

类与结构相似,因为它们使您可以使用属性和方法创建新类型,但是它们有五个重要的区别,我将一次向您介绍所有这些区别。

类和结构之间的第一个区别是类永远不会带有成员初始化器。这意味着,如果您的类中有属性,则必须始终创建自己的初始化程序。

例如:

class Dog {
    var name: String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}

创建该类的实例看起来就像是一个结构一样:

let poppy = Dog(name: "Poppy", breed: "Poodle")

类继承

类和结构之间的第二个区别是,您可以基于现有类创建一个类-它继承了原始类的所有属性和方法,并且可以在顶部添加自己的类。

这称为类继承或子类,您从其继承的类称为“父”或“超级”类,新类称为“子”类。

这是Dog我们刚刚创建的类:

class Dog {
    var name: String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}

我们可以基于一个名为的类创建一个新类Poodle。默认情况下,它将继承Dog相同的属性和初始化程序:

class Poodle: Dog {

}

但是,我们也可以提供Poodle自己的初始化程序。我们知道它将始终具有品种“贵宾犬”,所以我们可以做一个新的初始化器,只需要一个name属性。更好的是,我们可以让Poodle初始值设定项直接调用Dog初始值设定项,以便发生所有相同的设置::

class Poodle: Dog {
    init(name: String) {
        super.init(name: name, breed: "Poodle")
    }
}

出于安全原因,Swift总是让您super.init()从子类中进行调用-以防万一父类在创建时会做一些重要的工作。

覆盖方法

子类可以用其自己的实现替换父方法-这个过程称为Overriding。这是一个Dog带有makeNoise()方法的普通类:

class Dog {
    func makeNoise() {
        print("Woof!")
    }
}

如果我们创建一个Poodle继承自Dog的新类,它将继承该makeNoise()方法。因此,这将显示“ Woof!”:

class Poodle: Dog {
}

let poppy = Poodle()
poppy.makeNoise()

方法重写允许我们更改 Poodle类的makeNoise()实现。

Swift要求我们在重载方法时使用override func而不是仅仅使用func–它阻止您无意中重载方法,并且如果您尝试重载父类中不存在的内容,则会收到错误消息:

class Poodle: Dog {
    override func makeNoise() {
        print("Yip!")
    }
}

进行此更改后,poppy.makeNoise()将打印“ Yip!”而不是“ Woof!”。

Final类

尽管类继承非常有用-实际上苹果平台的大部分都需要您使用它-有时您还是想禁止其他开发人员根据您自己的类来构建他们的类。

Swift为此提供了一个关键字final:当您将一个类声明为final时,其他任何类都不能从该类继承。这意味着他们无法覆盖您的方法来更改您的行为–他们需要以编写类的方式使用您的类。

要使类最终定名,只需将final关键字放在其前面,如下所示:

final class Dog {
    var name: String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}

复制对象

类和结构之间的第三个区别是如何复制它们。复制结构时,原始结构和复制结构都是不同的-更改一个不会更改另一个。复制类时,原始副本和复制副本都指向同一件事,因此更改一个同时也会更改另一个。

例如,这是一个简单的Singer类,具有一个name具有默认值的属性:

class Singer {
    var name = "Taylor Swift"
}

如果创建该类的实例并打印其名称,则将得到“ Taylor Swift”:

var singer = Singer()
print(singer.name)

现在让我们从第一个变量创建第二个变量并更改其名称:

var singerCopy = singer
singerCopy.name = "Justin Bieber"

由于该方法的类的工作,既singer和singerCopy指向内存中的同一个对象,所以当我们打印歌手的名字,我们再次看到“Justin Bieber”:

print(singer.name)

另一方面,如果Singer是一个结构,那么我们将第二次打印“ Taylor Swift”:

struct Singer {
    var name = "Taylor Swift"
}

反初始化器

类和结构之间的第四个区别是,类可以具有反初始化器 -当类的实例被破坏时运行的代码。

为了说明这一点,这是一个Person带有name属性,简单的初始化程序和打印消息的printGreeting()方法的类:

class Person {
    var name = "John Doe"

    init() {
        print("\(name) is alive!")
    }

    func printGreeting() {
        print("Hello, I'm \(name)")
    }
}

我们将Person在循环中创建该类的一些实例,因为每次循环进行时,都会创建一个新人员,然后将其销毁:

for _ in 1...3 {
    let person = Person()
    person.printGreeting()
}

现在是反初始化器。Person实例销毁时将调用此方法:

deinit {
    print("\(name) is no more!")
}

可变性

类和结构之间的最终区别是它们处理常量的方式。如果您具有带有可变属性的常量结构,则该属性不能更改,因为结构本身是常量。

但是,如果您的常量类具有可变属性,则可以更改该属性。因此,类不需要带有mutating更改属性的方法的关键字。只有结构才需要。

这种差异意味着即使将类创建为常量,也可以更改类的任何变量属性–这是完全有效的代码:

class Singer {
    var name = "Taylor Swift"
}

let taylor = Singer()
taylor.name = "Ed Sheeran"
print(taylor.name)

如果要阻止这种情况发生,则需要使该属性不变:

class Singer {
    let name = "Taylor Swift"
}

总结

  • 1.类和结构相似,它们都可以让您使用属性和方法创建自己的类型。
  • 2.一个类可以从另一个类继承,并获得父类的所有属性和方法。谈论类层次结构是很常见的–一个类基于另一个类,而另一个类本身又基于另一个类。
  • 3.您可以使用final关键字标记一个类,这将阻止其他类从该类继承。
  • 4.通过方法覆盖,子类可以使用新的实现替换其父类中的方法。
  • 5.当两个变量指向同一类实例时,它们都指向同一块内存–一个会改变另一个。
  • 6.类可以具有一个反初始化器,该反初始化器是在销毁该类的实例时运行的代码。
  • 7类并不像构造结构那样强烈地强制执行常量–如果将属性声明为变量,则无论如何创建类实例,都可以对其进行更改。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容