迅捷cad
Continuing with our series of Swift tutorials, we’ll be discussing and playing around with another important element namely Swift Protocol in this tutorial. Furthemore we’ll be looking at the changes that Swift 4 brings in.
继续我们的Swift教程系列,我们将在本教程中讨论并研究另一个重要元素,即Swift协议 。 此外,我们将研究Swift 4带来的变化。
迅捷协议 (Swift Protocol)
Here’s how the Apple docs define a protocol.
苹果文档定义协议的方法如下。
If the above definition didn’t make complete sense to you here’s a simpler one.
如果上述定义对您没有完全意义,那么这是一个简单的定义。
Swift protocol is a basically a contract that a class/struct/enum can adopt to implement a specific set of methods and properties.
Swift协议基本上是类/结构/枚举可以用来实现一组特定方法和属性的契约。
In other words, to become THAT, you need to use THIS.
换句话说,要成为THAT,您需要使用THIS。
Swift协议语法 (Swift Protocol Syntax)
The syntax of Swift Protocol is similar to Classes, Structures and Enums.
protocol MyFirstProtocol{
//Properties and methods declarations go in here.
}
Classes, Structs and Enums can adopt the Protocol by placing it after the colon as shown below.
如下所示,类,结构和枚举可以通过将协议放在冒号后面来采用该协议。
class A : MyFirstProtocol{
//Enter your code
}
struct B : MyFirstProtocol{
//Enter your code
}
enum E : MyFirstProtocol {
//Enter your code
}
- If there are more than one protocols, they’re separated by commas. 如果协议不止一个,则以逗号分隔。
- If a class has a superclass, the superclass name would appear first, followed by the protocols. 如果类具有超类,则超类名称将首先出现,然后是协议。
protocol FirstProtocol{
//Properties and methods declarations goes in here.
}
protocol SecondProtocol{
//Properties and methods declarations goes in here.
}
class S {
//Let's say this is the super class.
}
class A : S,FirstProtocol, SecondProtocol{
//Enter your code
}
struct B : FirstProtocol, SecondProtocol{
//Enter your code
}
enum E : FirstProtocol, SecondProtocol {
//Enter your code
}
When a class/struct or enum conforms to a protocol, it must implement all of its methods to compile.
Let’s dive into the deep world of Protocols by starting our Playground in XCode.
当类/结构或枚举符合协议时,它必须实现其所有方法进行编译。
让我们通过XCode启动Playground,深入研究协议的深层世界。
Swift协议要求 (Swift Protocol Requirements)
- A protocol can contain properties as well as methods that the class/struct/enum conforming to the protocol would implement. 协议可以包含属性以及符合协议的类/结构/枚举将实现的方法。
- First things first, variables inside a protocol must be declared as a variable and not a constant(
let
isn’t allowed). 首先,协议内部的变量必须声明为变量,而不是常量(不允许let
)。 - Properties inside a protocol must contain the keyword
var
. 协议内的属性必须包含关键字var
。 - We need to explicitly specify the type of property(
{get}
or{get set}
).
Following are the two ways to do so. 我们需要明确指定属性的类型({get}
或{get set}
)。
以下是这样做的两种方法。 protocol FirstProtocol{ var age : Int {get set} //read-write property var year : Int {get} //optional write property }
- A {get set} computed property is readable as well as writable. For a {get}, it need not be settable.
In case the user wants to ensure that it’s readable only, they can change the property to a constant in the class. {get set}计算的属性既可读又可写。 对于{get},它不需要设置。
如果用户只想确保其可读性,则可以将属性更改为类中的常量。 class A : FirstProtocol{ var age = 23 var year = 2017 } var a = A() a.year = 2018 print(a.year) //prints 2018 //Alternative case class A : FirstProtocol{ var age = 23 let year = 2017 //now this is a constant. }
- Functions inside a protocol are defined without a body. 协议内部的功能无需主体即可定义。
- Default values within functions aren’t allowed. 函数中的默认值是不允许的。
- Functions with variadic parameters are also allowed. 也可以使用带有可变参数的函数。
- Mutating functions can be defined inside a keyword by adding the keyword
mutating
. 通过添加关键字mutating
,可以在关键字内定义更改功能。 - We do not need to write the
mutating
keyword when writing an implementation of that method for a class. 在为类编写该方法的实现时,我们不需要编写mutating
关键字。 - The
mutating
keyword is only used by structures and enumerations.mutating
关键字仅由结构和枚举使用。
Swift通讯协定范例 (Swift Protocol Example)
Let’s look at an example that uses the above swift protocol concepts.
让我们来看一个使用上述swift协议概念的示例。
protocol CSDegree{
var cgpa : Double {get set}
var name : String? {get set}
var coursesCompleted : Bool? {get set}
func haveYouCompletedOperatingSystems() -> Bool
func haveYouCompletedJavaCourse() -> Bool
func printAllGrades(grade: String...)
func degreeGranted()
mutating func hackToGetMyDegree()
}
class Student : CSDegree {
var cgpa: Double = 2
var name: String?
var coursesCompleted: Bool?
func haveYouCompletedJavaCourse() -> Bool {
return coursesCompleted ?? false
}
func haveYouCompletedOperatingSystems() -> Bool {
return coursesCompleted ?? false
}
func printAllGrades(grade: String...) {
if let n = name{
print("Grades of \(n) in all the courses are \(grade)")
}
else{
print("Student not found")
}
}
func degreeGranted() {
if haveYouCompletedJavaCourse() && haveYouCompletedOperatingSystems() && cgpa > 4
{
print("Congrats, you've completed Bachelors in Computer Science")
}
else{
print("Sorry, you won't be granted your degree this year")
}
}
func hackToGetMyDegree() {
cgpa = 8.5
coursesCompleted = true
}
}
var s = Student()
s.cgpa = 6.93
s.name = "Anupam"
s.coursesCompleted = false
print(s.name ?? "Not found") //prints "Anupam\n"
s.haveYouCompletedOperatingSystems()
s.haveYouCompletedJavaCourse()
s.degreeGranted() //Sorry, you won't be granted your degree this year
s.printAllGrades(grade: "A","D") //prints Grades of Anupam in all the courses are ["A", "D"]
Oops! Since my coursesCompleted
boolean property is false, the degreeGranted()
method isn’t giving me my degree. Let’s alter the property using the mutating function as shown below.
糟糕! 由于我的coursesCompleted
布尔值属性为false,因此degreeGranted()
方法无法获得我的学位。 让我们使用mutating函数来更改属性,如下所示。
s.hackToGetMyDegree()
s.degreeGranted() //prints Congrats, you've completed Bachelors in Computer Science
Similarly, we can use the protocol in a Structure as shown below.
同样,我们可以在如下所示的结构中使用该协议。
struct StudentStruct : CSDegree {
var cgpa: Double = 8.5
var name: String?
var coursesCompleted: Bool?
func haveYouCompletedJavaCourse() -> Bool {
return coursesCompleted ?? false
}
func haveYouCompletedOperatingSystems() -> Bool {
return coursesCompleted ?? false
}
func printAllGrades(grade: String...) {
if let n = name{
print("Grades of \(n) in all the courses are \(grade)")
}
else{
print("Student not found")
}
}
func degreeGranted() {
if haveYouCompletedJavaCourse() && haveYouCompletedOperatingSystems() && cgpa > 4
{
print("Congrats, you've completed Bachelors in Computer Science")
}
else{
print("Sorry, you won't be granted your degree this year")
}
}
mutating func hackToGetMyDegree() {
cgpa = 8.5
coursesCompleted = true
}
}
var s1 = StudentStruct()
s1.cgpa = 3.9
s1.name = "Anupam"
s1.coursesCompleted = false
print(s1.name ?? "Not found")
s1.haveYouCompletedOperatingSystems()
s1.haveYouCompletedJavaCourse()
s1.degreeGranted()
s1.printAllGrades(grade: "A","D")
s1.hackToGetMyDegree()
s1.degreeGranted()
带初始化器的Swift协议 (Swift Protocols With Intializers)
We can implement a swift protocol initializer requirement on a conforming class as either a designated initializer or a convenience initializer. For this, we must add the keyword required
before init
in the conforming class as shown below:
我们可以在符合条件的类上实现快速协议初始化程序要求,作为指定的初始化程序或便捷的初始化程序。 为此,我们必须在符合条件的类中的init
之前添加required
的关键字,如下所示:
protocol MyInitialiser {
init(name: String)
}
class TestInitProtocol : MyInitialiser{
required init(name: String) {
print("Welcome to \(name)")
}
}
var t = TestInitProtocol(name: "JournalDev") //prints Welcome to JournalDev\n"
//Convenience initializer example
protocol MyInitialiser {
init(name: String)
}
class TestInitProtocol : MyInitialiser{
convenience required init(name: String) {
print("Welcome to \(name)")
self.init()
}
}
var t = TestInitProtocol(name: "JournalDev")
Using Protocol Initialisers along with initialisers from SuperClass
将协议初始化程序与SuperClass的初始化程序一起使用
protocol MyInitialiser {
init()
}
class SuperClass{
init() {
}
}
class TestInitProtocol : SuperClass, MyInitialiser{
required override init() {
print("required from protocol, override from superclass")
}
}
var t = TestInitProtocol()
将Swift协议与扩展一起使用 (Using Swift Protocols With Extensions)
We can use Protocols on Extensions to add new properties, methods on an existing type.
我们可以使用扩展协议来在现有类型上添加新属性,方法。
protocol Greet
{
var str : String {get}
}
class Name{
var name: String?
}
extension Name : Greet{
var str : String {
return "Hello, \(name ?? "Mr. X")"
}
}
var n = Name()
n.name = "Anupam"
print(n.str) //prints "Hello, Anupam\n"
Protocol Extensions
Protocols can be extended to provide method and property implementations to conforming types. This way we can specify default values for properties in a protocol too as shown below.
协议扩展
可以扩展协议以为符合类型的方法和方法提供实现。 这样,我们也可以为协议中的属性指定默认值,如下所示。
protocol WebsiteName{
var name : String {get}
}
extension WebsiteName{
var name : String {
return "JournalDev"
}
}
class W : WebsiteName {
}
var w = W()
print(w.name)
带枚举的Swift协议 (Swift Protocols with Enums)
Consider the following case where a Protocol is implemented in an Enum.
考虑以下情况,其中在枚举中实现协议。
protocol ModifyCurrentDay
{
func currentDay() -> String
mutating func firstDayOfTheWeek()
}
enum DaysOfAWeek: String,ModifyCurrentDay{
case Sunday
case Monday
case Tuesday
case Wednesday
func currentDay()->String{
return self.rawValue
}
mutating func firstDayOfTheWeek() {
self = .Sunday
}
}
var day = DaysOfAWeek.Wednesday
print(day.currentDay()) //prints "Wednesday\n"
day.firstDayOfTheWeek()
print(day.currentDay()) //prints "Sunday\n"
Swift协议中的继承 (Inheritance in Swift Protocols)
A protocol can inherit one or more other protocols. This can be useful to add further requirements on top of the protocol. Doing so, the protocol that inherits other protocols would have to implement they’re methods and properties as well in the class/struct/enum. The syntax of protocol inheritance is similar to class inheritance as shown below
一个协议可以继承一个或多个其他协议。 这对于在协议顶部添加更多要求很有用。 这样做,继承其他协议的协议就必须在类/结构/枚举中实现它们的方法和属性。 协议继承的语法类似于类继承,如下所示
protocol A {
var length : Int {get set}
}
protocol B {
var breadth : Int {get set}
}
protocol C : A, B {
var height : Int {get set}
}
class Volume : C {
var height : Int = 5
var breadth: Int = 10
var length: Int = 2
func printVolume() {
print("Volume is \(height*breadth*length)")
}
}
var v = Volume()
v.printVolume() //prints 100
To limit a protocol to act as class-only protocols and not be used with structs/enums, the following syntax is used.
要将协议限制为仅用作类的协议,并且不与struct / enums一起使用,请使用以下语法。
protocol C : AnyObject, A, B {
var height : Int {get set}
}
The above protocol can’t be used with structs and enums since it extends AnyObject.
由于以上协议扩展了AnyObject,因此无法与结构和枚举一起使用。
Swift协议组成 (Swift Protocol Compositions)
Swift Protocols can be used as types inside a function too.
We can combine multiple protocols into a single composition and use them as an argument inside a function as shown below. We can list as many protocols as you need, separating them with ampersands (&). A single class type can also be included within the composition which is generally used to specify superclass.
Swift协议也可以用作函数内的类型。
我们可以将多个协议组合为一个组合,并将它们用作函数内的参数,如下所示。 我们可以根据需要列出任意数量的协议,并用&分隔。 单一类类型也可以包含在通常用于指定超类的组合中。
protocol A {
var length : Int {get set}
}
protocol B {
var breadth : Int {get set}
}
protocol C {
var height : Int {get set}
}
struct Volume : A, B, C {
var length: Int
var breadth: Int
var height: Int
}
func printVolume(to volume: A & B & C) {
print("Volume is \(volume.length*volume.breadth*volume.height)")
}
var v = Volume(length : 5, breadth: 5, height: 5)
printVolume(to: v) //prints 125
Swift 4混合协议和类 (Swift 4 Mixing Protocol and Classes)
With Swift 4 we can now combine protocols as types with classes too as shown below.
使用Swift 4,我们现在也可以将协议作为类型与类结合起来,如下所示。
protocol Name{}
protocol Age{}
class Zodiac{}
class Description{}
typealias Z = Name&Age&Zodiac
typealias D = Name&Age&Description
var nameAgeDescription : D
var nameAgeZodiac : Z
Adding a class to the protocol composition saves us from creating different subclasses for different types of classes from the above protocols and base classes.
在协议组成中添加一个类可以使我们免于为上述协议和基类的不同类型的类创建不同的子类。
可选协议要求 (Optional Protocol Requirements)
We can specify a property or method inside a protocol as optional. These requirements do not have to be implemented by types that conform to the protocol. To achieve this we need to specify the keyword @objc
before the keyword protocol and add the keyword @objc optional
for each optional properties/methods as shown below.
我们可以将协议内的属性或方法指定为可选。 这些要求不必通过符合协议的类型来实现。 为此,我们需要在关键字协议之前指定关键字@objc
,并为每个可选属性/方法添加关键字@objc optional
,如下所示。
@objc protocol OptionalPro{
@objc optional var name : String{get set}
@objc optional func printName()
func helloWord()
}
class O : OptionalPro{
func helloWord() {
print("hello world")
}
//Compiles fine without the need of implementing the optional requirements.
}
This brings an end to this tutorial on Swift Protocol.
这样就结束了有关Swift协议的本教程。
Reference: Apple Documentation
参考: Apple文档
迅捷cad