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