首页 iOS.& Swift Books Swift学徒

25
开奖结果3d方向编程 由ehab yosry amer撰写

Apple宣布Swift成为第一个 方形方向编程语言。这一宣言是通过引入实现的 开奖结果3d扩展名.

虽然从一开始,本公告的开奖结果3d已经在斯威夫特和开奖结果3d重标准库改变苹果生产,影响到你想想你的类型的方式。扩展开奖结果3d的关键是编程的一个全新的风格!

简单来说, 开奖结果3d方向编程 编码开奖结果3d的意大利者,概述特定类,结构或枚举。它通过打破旧开奖结果3d规则并允许您写作来实现这一点 实现 对于开奖结果3d本身的开奖结果3d。

本章介绍了开奖结果3d扩展和面向开奖结果3d的编程的权力。沿途,您将学习如何使用默认实现,键入约束,mixins和特征来简化您的代码。

介绍开奖结果3d扩展

您已在以前的章节中看到过扩展。他们允许您向类型添加其他方法和计算属性:

extension String {
  func shout() {
    print(uppercased())
  }
}

"Swift is pretty cool".shout()

Here, you’re extending the String type itself to add a new method. You can extend any type, including ones that you didn’t write yourself. You can have any number of extensions on a type.

你可以定义一个 开奖结果3d 使用以下语法扩展:

开奖结果3d TeamRecord {
  var wins: Int { get }
  var losses: Int { get }
  var winningPercentage: Double { get }
}

extension TeamRecord {
  var gamesPlayed: Int {
    wins + losses
  }
}

Like the way you extend a class, struct or enum, you use the keyword extension followed by the name of the protocol you are extending. Within the extension’s braces, you can define additional members on the protocol.

与ITSLILF的开奖结果3d相比,韦克罗利延伸中最具精简的导轨,是扩展属于实际的延伸 执行 of the member. In the example above, you define a new computed property named gamesPlayed that combines winslosses to return the total number of games played.

Although you haven’t written code for a concrete type that’s adopting the protocol, you can use the protocol members within its extension. That’s because the compiler knows that any type conforming to TeamRecord will have all the members required by TeamRecord.

Now you can write a simple type that adopts TeamRecord 和 use gamesPlayed without the need to reimplement it.

struct BaseballRecord: TeamRecord {
  var wins: Int
  var losses: Int

  var winningPercentage: Double {
    Double(wins) / Double(wins + losses)
  }
}

let sanFranciscoSwifts = BaseballRecord(wins: 10, losses: 5)
sanFranciscoSwifts.gamesPlayed // 15

Since BaseballRecord conforms to TeamRecord, you have access to gamesPlayed, defined in the protocol extension.

您可以看出有用的开奖结果3d扩展是如何在开奖结果3d上定义“免费”行为 - 但这只是一个开始。接下来,您将了解开奖结果3d扩展如何为开奖结果3d本身的成员提供实现。

默认实现

A protocol defines a contract for any type that adopts it. If a protocol defines a method or a property, any type that adopts the protocol must implement that method or property. Consider another example of a TeamRecord type:

struct BasketballRecord: TeamRecord {
  var wins: Int
  var losses: Int
  let seasonLength = 82

  var winningPercentage: Double {
    Double(wins) / Double(wins + losses)
  }
}
extension TeamRecord {
  var winningPercentage: Double {
    Double(wins) / Double(wins + losses)
  }
}
struct BasketballRecord: TeamRecord {
  var wins: Int
  var losses: Int
  let seasonLength = 82
}

let minneapolisFunctors = BasketballRecord(wins: 60, losses: 22)
minneapolisFunctors.winningPercentage
struct HockeyRecord: TeamRecord {
  var wins: Int
  var losses: Int
  var ties: Int

  // Hockey record introduces ties, and has
  // its own implementation of winningPercentage
  var winningPercentage: Double {
    Double(wins) / Double(wins + losses + ties)
  }
}
let chicagoOptionals = BasketballRecord(wins: 10, losses: 6)
let phoenixStridables = HockeyRecord(wins: 8, losses: 7, ties: 1)

chicagoOptionals.winningPercentage // 10 / (10 + 6) == 0.625
phoenixStridables.winningPercentage // 8 / (8 + 7 + 1) == 0.5

迷你练习

Write a default implementation on CustomStringConvertible that will simply remind you to implement description by returning Remember to implement CustomStringConvertible!.

struct MyStruct: CustomStringConvertible {}
print(MyStruct())
// should print "Remember to implement CustomStringConvertible!"

了解开奖结果3d扩展派遣

在定义开奖结果3d扩展时,有一个关键的GOTCHA。如果是一个类型 定义 开奖结果3d扩展中的方法或属性,没有 宣布 它在开奖结果3d本身, 静态调度 发挥作用。静态调度是指编译器根据它对类型所了解的内容选择编译时使用的方法或属性。编译器不考虑动态运行时信息。

开奖结果3d WinLoss {
  var wins: Int { get }
  var losses: Int { get }
}
extension WinLoss {
  var winningPercentage: Double {
    Double(wins) / Double(wins + losses)
  }
}
struct CricketRecord: WinLoss {
  var wins: Int
  var losses: Int
  var draws: Int

  var winningPercentage: Double {
    Double(wins) / Double(wins + losses + draws)
  }
}
let miamiTuples = CricketRecord(wins: 8, losses: 7, draws: 1)
let winLoss: WinLoss = miamiTuples

miamiTuples.winningPercentage // 0.5
winLoss.winningPercentage // 0.53 !!!

类型约束

For the protocol extensions on TeamRecord, you were able to use members of the TeamRecord protocol, such as winslosses, within the implementations of winningPercentagegamesPlayed. Much like in an extension on a struct, class or enum, you write code as if you were writing inside the type you’re extending.

开奖结果3d PostSeasonEligible {
  var minimumWinsForPlayoffs: Int { get }
}

extension TeamRecord where Self: PostSeasonEligible {
  var isPlayoffEligible: Bool { 
    wins > minimumWinsForPlayoffs
  }
}
struct HockeyRecord: TeamRecord {
  var wins: Int
  var losses: Int
  var ties: Int

  var winningPercentage: Double {
    Double(wins) / Double(wins + losses + ties)
  }
}
开奖结果3d Tieable {
  var ties: Int { get }
}
extension TeamRecord where Self: Tieable {
  var winningPercentage: Double {
    Double(wins) / Double(wins + losses + ties)
  }
}
struct RugbyRecord: TeamRecord, Tieable {
  var wins: Int
  var losses: Int
  var ties: Int
}

let rugbyRecord = RugyRecord(wins: 8, losses: 7, ties: 1)
rugbyRecord.winningPercentage // 0.5

迷你练习

Write a default implementation on CustomStringConvertible that will print the win/loss record in the format Wins - Losses for any TeamRecord type. For instance, if a team is 10 and 5, it should return 10 - 5.

开奖结果3d导向的福利

究竟是面向开奖结果3d的编程的好处是什么?

编程到接口,而不是实现

By focusing on protocols instead of implementations, you can apply code contracts to any type — even those that don’t support inheritance. Suppose you were to implement TeamRecord as a base class.

class TeamRecordBase {
  var wins = 0
  var losses = 0

  var winningPercentage: Double {
    Double(wins) / Double(wins + losses)
  }
}

// Will not compile: inheritance is only possible with classes.
struct BaseballRecord: TeamRecordBase {

}
class HockeyRecord: TeamRecordBase {
  var ties = 0

  override var winningPercentage: Double {
    Double(wins) / Double(wins + losses + ties)
  }
}
class TieableRecordBase: TeamRecordBase {
  var ties = 0

  override var winningPercentage: Double {
    Double(wins) / Double(wins + losses + ties)
  }
}

class HockeyRecord: TieableRecordBase {
}

class CricketRecord: TieableRecordBase {
}
extension TieableRecordBase {
  var totalPoints: Int {
    (2 * wins) + (1 * ties)
  }
}

特征,混合和多重遗传

偏离葡萄干的葡萄葡萄酒inflier或损失,开奖结果3d的真正福利之一是他们奥尔马尔奥尔特。

开奖结果3d TieableRecord {
  var ties: Int { get }
}

protocol DivisionalRecord {
  var divisionalWins: Int { get }
  var divisionalLosses: Int { get }
}

protocol ScoreableRecord {
  var totalPoints: Int { get }
}

extension ScoreableRecord where Self: TieableRecord, Self: TeamRecord {
  var totalPoints: Int {
    (2 * wins) + (1 * ties)
  }
}

struct NewHockeyRecord: TeamRecord, TieableRecord,
       DivisionalRecord, CustomStringConvertible, Equatable {
  var wins: Int
  var losses: Int
  var ties: Int
  var divisionalWins: Int
  var divisionalLosses: Int

  var description: String {
    "\(wins) - \(losses) - \(ties)"
  }
}

简单

当您编写计算属性以计算获胜百分比时,您只需要获胜,丢失和联系。当您编写代码来打印一个人的全名时,您只需要第一个和姓氏。

var winningPercentage: Double {
  var percent = Double(wins) / Double(wins + losses)

  // Oh no! Not relevant!
  above500 = percent > 0.5

  return percent
}

为什么Swift是一种面向议定的语言

您已经了解了开奖结果3d和开奖结果3d扩展的CAPABOL,对接您可能会恶化:它是什么精确的是mechad 议定书导向 language?

// From the Swift standard library
public struct Array<Element> : RandomAccessCollection, MutableCollection {
  // ...
}

挑战

在继续之前,这里有一些挑战来测试你的开奖结果3d,面向对象编程的知识。这是最好的尝试自行解决,但如果你卡住了解决方案可供选择。这些附带下载或可在介绍中列出的印刷书籍的源代码的链接。

挑战1:开奖结果3d扩展练习

Suppose you own a retail store. You have food items, clothes and electronics. Begin with an Item protocol:

开奖结果3d Item {
  var name: String { get }
  var clearance: Bool { get }
  var msrp: Double { get } // Manufacturer’s Suggested Retail Price
  var totalPrice: Double { get }
}

挑战2:翻倍

Write a protocol extension on Sequence named double() that only applies to sequences of numeric elements. Make it return an array where each element is twice the element in the sequence. Test your implementation on an array of Int 和 an array of Double, then see if you can try it on an array of String.

关键点

  • 开奖结果3d扩展名 允许您编写开奖结果3d的实现代码,甚至在开奖结果3d所需的方法上写入默认实现。
  • 开奖结果3d扩展是主要驱动程序 开奖结果3d方向编程 并允许您编写将在任何符合开奖结果3d的类型上工作的代码。
  • 类型约束 在开奖结果3d扩展中提供了其他上下文,并让您编写更专业化的实现。
  • 您可以使用类型装饰 特征混合 扩展行为而不需要继承。
  • 开奖结果3d,使用井时,促进代码重用和封装。
  • 从价值类型开始并找到基本开奖结果3d。

有一个技术问题?想报告一个错误吗? 您可以向官方书籍论坛中的书籍作者提出问题和报告错误 这里.

有反馈分享在线阅读体验吗? 如果您与UUR在线阅读器的UI,UX,Heativisting或其他功能有反馈,您可以使用下文:

© 2021 Razeware LLC

您可以免费读取,本章的部分显示为 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

要突出或记笔记,您需要在订阅中拥有这本书或自行购买。