★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10470993.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

方法是与特定类型相关联的函数。类,结构和枚举都可以定义实例方法,这些方法封装了用于处理给定类型的实例的特定任务和功能。类,结构和枚举也可以定义类型方法,它们与类型本身相关联。类型方法类似于Objective-C中的类方法。

结构和枚举可以在Swift中定义方法的事实是与C和Objective-C的主要区别。在Objective-C中,类是唯一可以定义方法的类型。在Swift中,您可以选择是定义类,结构还是枚举,并且仍然可以灵活地在您创建的类型上定义方法。

实例方法

实例方法是属于特定类,结构或枚举的实例的函数。它们通过提供访问和修改实例属性的方法,或通过提供与实例目的相关的功能来支持这些实例的功能。实例方法具有完全相同的语法功能,如描述的功能。

您在其所属类型的开始和结束括号内编写实例方法。实例方法可以隐式访问该类型的所有其他实例方法和属性。实例方法只能在其所属类型的特定实例上调用。如果没有现有实例,则无法单独调用它。

这是一个定义简单Counter类的示例,可用于计算操作发生的次数:

  1. class Counter {
  2. var count = 0
  3. func increment() {
  4. count += 1
  5. }
  6. func increment(by amount: Int) {
  7. count += amount
  8. }
  9. func reset() {
  10. count = 0
  11. }
  12. }

Counter类定义了三个实例方法:

  • increment()递增计数器1
  • increment(by: Int) 将计数器递增指定的整数。
  • reset() 将计数器重置为零。

Counter类还声明一个变量属性count,以跟踪当前计数器值。

使用与属性相同的点语法调用实例方法:

  1. let counter = Counter()
  2. // the initial counter value is 0
  3. counter.increment()
  4. // the counter's value is now 1
  5. counter.increment(by: 5)
  6. // the counter's value is now 6
  7. counter.reset()
  8. // the counter's value is now 0

函数参数既可以具有名称(在函数体内使用),也可以具有参数标签(在调用函数时使用),如函数参数标签和参数名称中所述。方法参数也是如此,因为方法只是与类型相关联的函数。

自我属性

类型的每个实例都有一个名为的隐式属性self,它与实例本身完全等效。您可以使用该self属性在其自己的实例方法中引用当前实例。

increment()上面示例中的方法可能是这样编写的:

  1. func increment() {
  2. self.count += 1
  3. }

实际上,您不需要self经常编写代码。如果您没有显式写入self,则Swift会假定您在方法中使用已知属性或方法名称时引用当前实例的属性或方法。这个假设通过在三个实例方法中使用count(而不是self.count)来证明Counter

当实例方法的参数名称与该实例的属性具有相同的名称时,会发生此规则的主要例外。在这种情况下,参数名称优先,并且有必要以更合格的方式引用属性。您可以使用该self属性来区分参数名称和属性名称。

这里,self消除了调用的方法参数x和也被称为的实例属性之间的歧义x

  1. struct Point {
  2. var x = 0.0, y = 0.0
  3. func isToTheRightOf(x: Double) -> Bool {
  4. return self.x > x
  5. }
  6. }
  7. let somePoint = Point(x: 4.0, y: 5.0)
  8. if somePoint.isToTheRightOf(x: 1.0) {
  9. print("This point is to the right of the line where x == 1.0")
  10. }
  11. // Prints "This point is to the right of the line where x == 1.0"

如果没有self前缀,Swift会假设两种x方法都引用了被调用的方法参数x

从实例方法中修改值类型

结构和枚举是值类型。默认情况下,无法在其实例方法中修改值类型的属性。

但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择改变该方法的行为。然后,该方法可以从方法中改变(即更改)其属性,并且当方法结束时,它所做的任何更改都将写回原始结构。该方法还可以为其隐式self属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。

您可以通过将mutating关键字放在该方法的关键字之前来选择此行为func

  1. struct Point {
  2. var x = 0.0, y = 0.0
  3. mutating func moveBy(x deltaX: Double, y deltaY: Double) {
  4. x += deltaX
  5. y += deltaY
  6. }
  7. }
  8. var somePoint = Point(x: 1.0, y: 1.0)
  9. somePoint.moveBy(x: 2.0, y: 3.0)
  10. print("The point is now at (\(somePoint.x), \(somePoint.y))")
  11. // Prints "The point is now at (3.0, 4.0)"

Point上面的结构定义了一个变异moveBy(x:y:)方法,它将Point实例移动一定量。此方法实际上修改了调用它的点,而不是返回一个新点。该mutating关键字被添加到它的定义,使之能够修改其属性。

请注意,您不能在结构类型的常量上调用变异方法,因为它的属性不能更改,即使它们是变量属性,如常量结构实例的存储属性中所述:

  1. let fixedPoint = Point(x: 3.0, y: 3.0)
  2. fixedPoint.moveBy(x: 2.0, y: 3.0)
  3. // this will report an error

在变异方法中分配给自我

变异方法可以为隐式self属性分配一个全新的实例。Point上面显示的示例可能是以下列方式编写的:

  1. struct Point {
  2. var x = 0.0, y = 0.0
  3. mutating func moveBy(x deltaX: Double, y deltaY: Double) {
  4. self = Point(x: x + deltaX, y: y + deltaY)
  5. }
  6. }

此版本的mutating moveBy(x:y:)方法创建一个新结构,其值xy值设置为目标位置。调用该方法的替代版本的最终结果与调用早期版本完全相同。

枚举的变异方法可以将隐式self参数设置为与同一枚举不同的大小写:

  1. enum TriStateSwitch {
  2. case off, low, high
  3. mutating func next() {
  4. switch self {
  5. case .off:
  6. self = .low
  7. case .low:
  8. self = .high
  9. case .high:
  10. self = .off
  11. }
  12. }
  13. }
  14. var ovenLight = TriStateSwitch.low
  15. ovenLight.next()
  16. // ovenLight is now equal to .high
  17. ovenLight.next()
  18. // ovenLight is now equal to .off

此示例定义三态切换的枚举。每次调用其方法时off,开关在三种不同的电源状态(,lowhigh)之间循环next()

类型方法

如上所述,实例方法是您在特定类型的实例上调用的方法。您还可以定义在类型本身上调用的方法。这些方法称为类型方法。通过static在方法的func关键字之前写入关键字来指示类型方法。类可以使用class关键字,以允许子类覆盖超类的该方法的实现。

注意

在Objective-C中,您只能为Objective-C类定义类型级方法。在Swift中,您可以为所有类,结构和枚举定义类型级方法。每种类型方法都明确限定为它支持的类型。

使用点语法调用类型方法,例如实例方法。但是,您在类型上调用类型方法,而不是在该类型的实例上调用。以下是在类调用上调用类型方法的方法SomeClass

  1. class SomeClass {
  2. class func someTypeMethod() {
  3. // type method implementation goes here
  4. }
  5. }
  6. SomeClass.someTypeMethod()

在类型方法的主体内,隐式self属性引用类型本身,而不是该类型的实例。这意味着您可以使用self消除类型属性和类型方法参数之间的歧义,就像您对实例属性和实例方法参数一样。

更一般地,您在类型方法的主体中使用的任何非限定方法和属性名称将引用其他类型级别的方法和属性。类型方法可以使用另一个方法的名称调用另一个类型方法,而无需使用类型名称作为前缀。类似地,结构和枚举上的类型方法可以通过使用不带类型名称前缀的type属性的名称来访问类型属性。

下面的示例定义了一个名为的结构LevelTracker,它跟踪玩家在游戏的不同级别或阶段的进度。这是一款单人游戏,但可以在一台设备上存储多个玩家的信息。

首次玩游戏时,所有游戏的等级(除了第一级)都被锁定。每当玩家完成一个等级时,该等级就会被设备上的所有玩家解锁。该LevelTracker结构使用类型属性和方法来跟踪游戏的哪些级别已解锁。它还跟踪单个玩家的当前等级。

  1. struct LevelTracker {
  2. static var highestUnlockedLevel = 1
  3. var currentLevel = 1
  4. static func unlock(_ level: Int) {
  5. if level > highestUnlockedLevel { highestUnlockedLevel = level }
  6. }
  7. static func isUnlocked(_ level: Int) -> Bool {
  8. return level <= highestUnlockedLevel
  9. }
  10. @discardableResult
  11. mutating func advance(to level: Int) -> Bool {
  12. if LevelTracker.isUnlocked(level) {
  13. currentLevel = level
  14. return true
  15. } else {
  16. return false
  17. }
  18. }
  19. }

LevelTracker结构跟踪任何玩家解锁的最高级别。该值存储在名为的类型属性中highestUnlockedLevel

LevelTracker还定义了两个类型函数来处理highestUnlockedLevel属性。第一个是调用的类型函数unlock(_:),它会更新highestUnlockedLevel解锁新级别时的值。第二个是调用的便捷类型函数isUnlocked(_:)true如果特定的级别编号已经解锁,则返回该函数。(请注意,这些类型方法可以访问highestUnlockedLeveltype属性,而无需将其写为LevelTracker.highestUnlockedLevel。)

除了类型属性和类型方法之外,还可以LevelTracker跟踪单个玩家在游戏中的进度。它使用一个名为的实例属性currentLevel来跟踪玩家当前正在玩的等级。

要帮助管理currentLevel属性,请LevelTracker定义一个名为的实例方法advance(to:)。在更新之前currentLevel,此方法检查所请求的新级别是否已解锁。该advance(to:)方法返回一个布尔值,以指示它是否实际上能够设置currentLevel。因为调用advance(to:)方法忽略返回值的代码不一定是错误,所以此函数用@discardableResult属性标记。有关此属性的更多信息,请参阅属性。

LevelTracker结构与Player下面所示的类一起使用,以跟踪和更新单个玩家的进度:

  1. class Player {
  2. var tracker = LevelTracker()
  3. let playerName: String
  4. func complete(level: Int) {
  5. LevelTracker.unlock(level + 1)
  6. tracker.advance(to: level + 1)
  7. }
  8. init(name: String) {
  9. playerName = name
  10. }
  11. }

Player类创建的新实例LevelTracker来跟踪玩家的进展。它还提供了一个名为的方法complete(level:),只要玩家完成特定级别就会调用该方法。此方法为所有玩家解锁下一关,并更新玩家的进度以将其移至下一关。(advance(to:)忽略布尔返回值,因为已知通过LevelTracker.unlock(_:)上一行的调用解锁了该级别。)

您可以Player为新玩家创建该类的实例,并查看玩家完成第一级时会发生什么:

  1. var player = Player(name: "Argyrios")
  2. player.complete(level: 1)
  3. print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
  4. // Prints "highest unlocked level is now 2"

如果你创建了第二个玩家,你试图将其移动到游戏中任何玩家尚未解锁的等级,那么设置玩家当前等级的尝试将失败:

  1. player = Player(name: "Beto")
  2. if player.tracker.advance(to: 6) {
  3. print("player is now on level 6")
  4. } else {
  5. print("level 6 has not yet been unlocked")
  6. }
  7. // Prints "level 6 has not yet been unlocked"

转载于:https://www.cnblogs.com/strengthen/p/9739153.html

Swift5.1 语言指南(十三) 方法相关推荐

  1. Swift5.1 语言指南(二十三) 协议

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  2. Swift5.1 语言指南(一) 关于Swift

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  3. Swift5.1 语言指南(三) 快速之旅

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  4. Swift5.1 语言指南(九) 闭包

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  5. Swift5.1 语言指南(二十) 类型转换

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  6. Swift语言指南(十)--字符串与字符

    原文:Swift语言指南(十)--字符串与字符 字符串是一段字符的有序集合,如"hellow,world"或"信天翁".Swift 中的字符串由 String ...

  7. Protobuf3语言指南

    参考文章:http://blog.csdn.net/u011518120/article/details/54604615 英文原文:  Language Guide (proto3)  中文出处:  ...

  8. GitHub上Swift语言指南

    Swift 语言指南 @SwiftLanguage 更新于 2016-6-6,更新内容详见 Issue 55.往期更新回顾详见<收录周报> 这份指南汇集了 Swift 语言主流学习资源,并 ...

  9. 关于一些C语言代码优化的方法,我慷慨解囊了大家酌情收藏

    关于一些C语言代码优化的方法,我慷慨解囊了大家酌情收藏 简介 在最近的一个项目中,我们需要开发一个运行在移动设备上但不保证图像高质量的轻量级JPEG库.期间,我总结了一些让程序运行更快的方法.在本篇文 ...

最新文章

  1. ssh免密连接远程服务器
  2. 大规模神经网络的训练优化入门
  3. 不经保存,直接读取上传文件
  4. CentOS忘记root密码解决办法
  5. [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵
  6. Python中的顺序表介绍
  7. 【hiho一下 第147周】小Hi的烦恼
  8. 如何优化MySQL千万级大表,我写了6000字的解读
  9. 微云网页版服务器繁忙,腾讯微云传输速度慢的几种原因及解决方法
  10. linux php安装xsl扩展,11.32 php扩展模块安装
  11. 【系统架构】原型图验收的思考
  12. 职场减压移魂大法几则 (转东转西)
  13. oracle大型数据库系统在aix/unix上的实战详解 pdf,Oracle10g在AIX上的安装准备工作《Oracle大型数据库系统在AIX/unix上的实战详解》集中答疑40...
  14. ftp连接服务器失败:响应:220-FileZilla Server version 0.9.24 beta 响应:220-written by Tim Kosse (Tim.Kosse@gmx.d
  15. JavaCV音视频开发宝典:JavaCV使用gdigrab方式实现windows录屏(windows屏幕画面抓取/采集,可实现高帧率屏幕截屏、录屏功能)
  16. 学习记录【1】--chrome的控制台打开很慢
  17. ROS IDE —— RoboWare Studio
  18. 全景图的种类及opencv实现
  19. 转自菜头 英超,给技术人员一点时间
  20. asp另存为文件名-名称-类型

热门文章

  1. win7如何显示文件后缀
  2. 用户交互设计10个可用性指标
  3. 系统可用性分析方法与设计模板
  4. 【STM32学习笔记】(9)——串口通讯(USART)详解
  5. mysql数据库中到底能建多少张表?(单实例下单个库)
  6. 自我管理数据缓冲区内存
  7. 手淘Android容器架构——Atlas的前世今生
  8. 流程配置中,什么是会签/或签(竞签)
  9. 高屋建瓴学机器学习/深度学习
  10. 解决 Windows中丢失d3dx9_39.dll