专栏首页韦弦的偶尔分享100 Days of SwiftUI —— Day 10:类

100 Days of SwiftUI —— Day 10:类

最初,类看起来与结构体非常相似,因为我们使用它们来创建具有属性和方法的新数据类型。但是,它们引入了一个新的,重要的且复杂的功能,即继承——使一个类在另一个类的基础上构建的能力。

这是一项强大的功能,毫无疑问,当您开始构建真实的iOS应用程序时,也无法避免使用类。但是请记住要保持代码简单:仅因为功能存在,并不意味着您需要使用它。正如马丁·福勒(Martin Fowler)所说,“任何傻瓜都可以编写计算机可以理解的代码,但是优秀的程序员可以编写人类可以理解的代码。(any fool can write code that a computer can understand, but good programmers write code that humans can understand.)”

我已经说过,SwiftUI在其UI设计中广泛使用结构体。嗯,它在数据中广泛使用类:当您在屏幕上显示某个对象的数据,或者在布局之间传递数据时,通常会使用类。

我应该补充一点:如果您以前曾经使用过UIKit,这对您来说将是一个不一样的转变——在UIKit中,我们通常使用类进行UI设计并使用结构进行数据处理。因此,如果您认为您可以在这里跳过一天,那么抱歉,您不能这样做:这是必需的。

今天,您有8个一分钟的视频可供观看,并且您将遇到方法重写最终类反初始化器等问题。观看完每个视频后,我们会进行一次简短的测试,以帮助您了解所教的内容。

1. 创建自己的类 Creating your own classestest

类与结构体相似,它们使您可以使用属性和方法创建新类型,但是它们有五个重要的区别,我将逐步介绍每个区别。

类和结构体之间的

类永远不会带有成员初始化器。这意味着,如果您的类中有属性,则必须创建自己的初始化程序。 例如:

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")

2. 类继承 Class inheritancetest

类和结构之间的

是,您可以基于现有类创建一个类——它继承了原始类的所有属性和方法,并且可以在其顶部添加自己的属性。

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

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

class Poodle: Dog {

}

但是,我们也可以给Poodle提供自己的初始化程序。我们知道它将始终具有品种“ Poodle”,因此我们可以创建一个仅需要name属性的新初始化程序。更好的是,我们可以使Poodle初始化程序直接调用Dog初始化程序,以便进行所有相同的设置:

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

为了安全起见,Swift总是让您从子类中调用super.init(),以防万一父类在创建时会做一些重要的工作。

3. 方法重写 Overriding methodstest

子类可以使用其自己的实现替换父方法——这个过程称为重写。这是一个带有makeNoise()方法的简单Dog类:

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

如果我们创建一个从Dog继承的新Poodle类,它将继承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!”。

4. 最终类 Final classestest

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

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

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

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

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

5. 拷贝对象 Copying objectstest

类和结构体之间的

是如何复制它们。复制结构体时,原始结构体和复制结构体都是不同的——更改一个结构体不会更改另一个结构体。复制一个类时,原始副本和复制副本都指向同一事物,因此更改一个类会同时更改另一个。

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

class Singer {
    var name = "Taylor Swift"
}

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

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

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

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

由于类的工作方式,singersingerCopy都指向内存中的同一对象,因此当我们再次打印歌手名称时,将看到“ Justin Bieber”:

print(singer.name)

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

struct Singer {
    var name = "Taylor Swift"
}

6. 反初始化器 Deinitializerstest

类和结构之间的

是类可以具有反初始化器——当类的实例被销毁时运行的代码。

为了说明这一点,这里是一个Person类,它具有name属性,一个简单的初始化程序以及一个用于打印消息的printGreeting()方法:

class Person {
    var name = "John Doe"

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

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

我们将在一个循环中创建Person类的一些实例,因为每次循环时都会创建一个新的person并销毁它:

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

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

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

7. 可变性 Mutabilitytest

类和结构体之间的

是它们处理常量的方式。如果您具有带有可变属性的常量结构,则该属性无法更改,因为结构体本身是常量。

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

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

class Singer {
    var name = "Taylor Swift"
}

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

如果要阻止这种情况发生,则需要使该属性为常量:

class Singer {
    let name = "Taylor Swift"
}

8. 类:总结 Classes summarytest

您已经完成了本系列第八部分,所以让我们总结一下:

1、类和结构体相似,它们都可以让您使用属性和方法创建自己的类型。 2、一个类可以从另一个类继承,并获得父类的所有属性和方法。讨论类层次结构很常见——一个类基于另一个类,而另一个类本身又基于另一个类。 3、您可以使用final关键字标记一个类,这将阻止其他类从该类继承。 4、通过方法重写,子类可以使用新的实现替换其父类中的方法。 5、当两个变量指向同一类实例时,它们都指向同一块内存——改变一个会改变另一个。 6、类可以具有一个反初始化器,该反初始化器是在销毁该类的实例时运行的代码。 7、类对常量的强制性不如结构强——如果将属性声明为变量,则无论如何创建类实例,都可以对其进行更改。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SwiftU:将状态绑定到UI控件

    SwiftUI的@State属性包装器允许我们自由修改视图结构体,这意味着当程序更改时,我们可以更新视图属性以匹配。

    韦弦zhy
  • 微信小程序后台返回大量多余数据的处理

    其实我只要id和name,找后台解决、、、算了吧,奈何天生就是个儒生,温文尔雅,打架是打不赢的,要是能打赢的就直接打吧,打完让他们改!

    韦弦zhy
  • Swift入门: 字符串插值

    如果我们想打印一条消息给包含他们姓名的用户,字符串插值就变得很简单:只需编写一个反斜杠、一个左括号、一个代码、一个右括号,如下所示:

    韦弦zhy
  • ES6特性之:箭头函数

    在ES6的所有新特性中,箭头函数(Arrow Fucntion)算是我用的最频繁的特性之一了。

    一斤代码
  • 小朋友学C++(6):this指针

    this指针是一个隐含于类中的特殊指针,指向对象本身。也就是说对象一旦被创建,this指针也就存在了。 就好比你的名字叫做Teodoro,别人说你的时候用的是T...

    海天一树
  • 【Python基础】函数的返回

    很多时候,函数并非直接输出,相反,它可以处理一些数据,并返回一个值或者一组值,称之为返回值。

    DataScience
  • python PAM30 PAMIE

    安装PAM30,由于没有直接的安装文件 需要下载压缩包 然后把压缩吧解压至python/Lib/site-package/下

    py3study
  • Echart在Openlayers的应用-航班的炫光特效

    在前两篇文章中讲到了echart在openlayers2中的应用,地图统计图与热力图的实现,在本文中介绍openlayers中结合echart实现航班的炫光特效...

    lzugis
  • redis缓存数据库

    NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系数据库在应...

    菲宇
  • 【python】redis模块

    windows下载地址:https://github.com/MSOpenTech/redis/releases

    py3study

扫码关注云+社区

领取腾讯云代金券