Swift - Giao thức

Các giao thức cung cấp bản thiết kế cho các Phương thức, thuộc tính và các chức năng yêu cầu khác. Nó chỉ được mô tả như một phương thức hoặc khung thuộc tính thay vì thực thi. Việc triển khai các phương thức và thuộc tính có thể được thực hiện nhiều hơn nữa bằng cách xác định các lớp, hàm và liệt kê. Sự phù hợp của một giao thức được định nghĩa là các phương thức hoặc thuộc tính thỏa mãn các yêu cầu của giao thức.

Cú pháp

Các giao thức cũng tuân theo cú pháp tương tự như của các lớp, cấu trúc và kiểu liệt kê -

protocol SomeProtocol {
   // protocol definition 
}

Các giao thức được khai báo sau tên lớp, cấu trúc hoặc kiểu liệt kê. Cũng có thể khai báo một giao thức và nhiều giao thức. Nếu nhiều giao thức được xác định, chúng phải được phân tách bằng dấu phẩy.

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

Khi một giao thức phải được định nghĩa cho siêu lớp, tên giao thức phải theo sau tên siêu lớp với dấu phẩy.

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

Yêu cầu về tài sản và phương pháp

Giao thức được sử dụng để chỉ định thuộc tính loại lớp cụ thể hoặc thuộc tính cá thể. Nó chỉ chỉ định loại hoặc thuộc tính cá thể một mình thay vì chỉ định đó là thuộc tính được lưu trữ hay tính toán. Ngoài ra, nó được sử dụng để chỉ định xem thuộc tính là 'gettable' hay 'có thể thiết lập được'.

Các yêu cầu thuộc tính được khai báo bởi từ khóa 'var' dưới dạng các biến thuộc tính. {get set} được sử dụng để khai báo các thuộc tính gettable và có thể thiết lập sau khi khai báo kiểu của chúng. Gettable được thuộc tính {get} đề cập sau phần khai báo kiểu của chúng.

protocol classa {
   var marks: Int { get set }
   var result: Bool { get }
   
   func attendance() -> String
   func markssecured() -> String
}

protocol classb: classa {
   var present: Bool { get set }
   var subject: String { get set }
   var stname: String { get set }
}

class classc: classb {
   var marks = 96
   let result = true
   var present = false
   var subject = "Swift 4 Protocols"
   var stname = "Protocols"

   func attendance() -> String {
      return "The \(stname) has secured 99% attendance"
   }
   func markssecured() -> String {
      return "\(stname) has scored \(marks)"
   }
}

let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

98
true
false
Swift 4 Protocols
Swift 4

Yêu cầu về phương pháp đột biến

protocol daysofaweek {
   mutating func print()
}

enum days: daysofaweek {
   case sun, mon, tue, wed, thurs, fri, sat 
   mutating func print() {
      switch self {
         case sun:
            self = sun
            print("Sunday")
         case mon:
            self = mon
            print("Monday")
         case tue:
            self = tue
            print("Tuesday")
         case wed:
            self = wed
            print("Wednesday")
         case mon:
            self = thurs
            print("Thursday")
         case tue:
            self = fri
            print("Friday")
         case sat:
            self = sat
            print("Saturday")
         default:
            print("NO Such Day")
      }
   }
}

var res = days.wed
res.print()

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Wednesday

Yêu cầu khởi tạo

Swing cho phép người dùng khởi tạo các giao thức để tuân theo kiểu tương tự như của các trình khởi tạo thông thường.

Cú pháp

protocol SomeProtocol {
   init(someParameter: Int)
}

Ví dụ

protocol tcpprotocol {
   init(aprot: Int)
}

Triển khai lớp các yêu cầu của bộ khởi tạo giao thức

Bộ khởi tạo được chỉ định hoặc tiện lợi cho phép người dùng khởi tạo một giao thức để phù hợp với tiêu chuẩn của nó bằng từ khóa 'bắt buộc' dành riêng.

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

Sự tuân thủ giao thức được đảm bảo trên tất cả các lớp con để triển khai rõ ràng hoặc kế thừa bởi công cụ sửa đổi 'bắt buộc'.

Khi một lớp con ghi đè yêu cầu khởi tạo siêu lớp của nó, nó được chỉ định bởi từ khóa bổ trợ 'ghi đè'.

protocol tcpprotocol {
   init(no1: Int)
}

class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}

class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

res is: 20
res is: 30
res is: 50

Giao thức dưới dạng các loại

Thay vì triển khai các chức năng trong một giao thức, chúng được sử dụng làm kiểu cho các hàm, lớp, phương thức, v.v.

Các giao thức có thể được truy cập dưới dạng các loại trong -

  • Hàm, phương thức hoặc khởi tạo dưới dạng tham số hoặc kiểu trả về

  • Hằng số, biến hoặc thuộc tính

  • Mảng, từ điển hoặc các vùng chứa khác dưới dạng các mục

protocol Generator {
   typealias members
   func next() -> members?
}

var items = [10,20,30].generate()
while let x = items.next() {
   print(x)
}

for lists in map([1,2,3], {i in i*5}) {
   print(lists)
}

print([100,200,300])
print(map([1,2,3], {i in i*10}))

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

Thêm sự tuân thủ giao thức với một phần mở rộng

Loại hiện tại có thể được chấp nhận và tuân theo một giao thức mới bằng cách sử dụng các tiện ích mở rộng. Các thuộc tính, phương pháp và chỉ số phụ mới có thể được thêm vào các loại hiện có với sự trợ giúp của tiện ích mở rộng.

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}
class Person {
   let firstname: String
   let lastname: String
   var age: Int
   
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   func agetype() -> String {
      switch age {
         case 0...2:
            return "Baby"
         case 2...12:
            return "Child"
         case 13...19:
            return "Teenager"
         case let x where x > 65:
            return "Elderly"
         default:
            return "Normal"
      }
   }
}

Kế thừa giao thức

Swift 4 cho phép các giao thức kế thừa các thuộc tính từ các thuộc tính đã xác định của nó. Nó tương tự như kế thừa lớp, nhưng với sự lựa chọn liệt kê nhiều giao thức kế thừa được phân tách bằng dấu phẩy.

protocol classa {
   var no1: Int { get set }
   func calc(sum: Int)
}
protocol result {
   func print(target: classa)
}
class student2: result {
   func print(target: classa) {
      target.calc(sum: 1)
   }
}
class classb: result {
   func print(target: classa) {
      target.calc(sum: 5)
   }
}

class student: classa {
   var no1: Int = 10
   
   func calc(sum: Int) {
      no1 -= sum
      print("Student attempted \(sum) times to pass")
         
      if no1 <= 0 {
         print("Student is absent for exam")
      }
   }
}

class Player {
   var stmark: result!

   init(stmark: result) {
      self.stmark = stmark
   }
   func print(target: classa) {
      stmark.print(target: target)
   }
}

var marks = Player(stmark: student2())
var marksec = student()

marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam

Giao thức chỉ lớp học

Khi các giao thức được định nghĩa và người dùng muốn định nghĩa giao thức với các lớp, nó nên được thêm vào bằng cách xác định lớp trước, sau đó là danh sách kế thừa của giao thức.

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

res is: 20
res is: 30
res is: 50

Thành phần giao thức

Swift 4 cho phép nhiều giao thức được gọi cùng một lúc với sự trợ giúp của thành phần giao thức.

Cú pháp

protocol<SomeProtocol, AnotherProtocol>

Thí dụ

protocol stname {
   var name: String { get }
}
protocol stage {
   var age: Int { get }
}
struct Person: stname, stage {
   var name: String
   var age: Int
}
func print(celebrator: stname & stage) {
   print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

Kiểm tra sự tuân thủ giao thức

Sự phù hợp của giao thức được kiểm tra bởi các toán tử 'is' và 'as' tương tự như của kiểu đúc.

  • Toán tử is trả về true nếu một phiên bản tuân theo tiêu chuẩn giao thức và trả về false nếu nó không thành công.

  • Các as? phiên bản của toán tử downcast trả về một giá trị tùy chọn của kiểu giao thức và giá trị này là 0 nếu phiên bản không phù hợp với giao thức đó.

  • Phiên bản as của toán tử downcast buộc downcast đến loại giao thức và gây ra lỗi thời gian chạy nếu downcast không thành công.

import Foundation

@objc protocol rectangle {
   var area: Double { get }
}
@objc class Circle: rectangle {
   let pi = 3.1415927
   var radius: Double
   var area: Double { return pi * radius * radius }
   init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
   var area: Double
   init(area: Double) { self.area = area }
}
class sides {
   var rectsides: Int
   init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]

for object in objects {
   if let objectWithArea = object as? rectangle {
      print("Area is \(objectWithArea.area)")
   } else {
      print("Rectangle area is not defined")
   }
}

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Area is 12.5663708
Area is 198.0
Rectangle area is not defined