Swift - Kiểm soát truy cập

Để hạn chế quyền truy cập vào các khối mã, mô-đun và sự trừu tượng được thực hiện thông qua kiểm soát truy cập. Các lớp, cấu trúc và bảng liệt kê có thể được truy cập theo thuộc tính, phương thức, bộ khởi tạo và chỉ số con của chúng bằng cơ chế kiểm soát truy cập. Hằng số, biến và hàm trong một giao thức bị hạn chế và được phép truy cập như toàn cục và cục bộ thông qua kiểm soát truy cập. Kiểm soát truy cập áp dụng cho các thuộc tính, loại và chức năng có thể được gọi là 'thực thể'.

Mô hình kiểm soát truy cập dựa trên mô-đun và tệp nguồn.

Mô-đun được định nghĩa là một đơn vị phân phối mã duy nhất và có thể được nhập bằng từ khóa 'nhập'. Tệp nguồn được định nghĩa là một tệp mã nguồn duy nhất có trong một mô-đun để truy cập nhiều loại và chức năng.

Ngôn ngữ Swift 4 cung cấp ba cấp độ truy cập khác nhau. Chúng là quyền truy cập Công khai, Nội bộ và Riêng tư.

S. không Cấp độ Truy cập & Định nghĩa
1

Public

Cho phép các thực thể được xử lý với bất kỳ tệp nguồn nào từ mô-đun xác định của chúng, tệp nguồn từ mô-đun khác nhập mô-đun xác định.

2

Internal

Cho phép các thực thể được sử dụng trong bất kỳ tệp nguồn nào từ mô-đun xác định của chúng, nhưng không được sử dụng trong bất kỳ tệp nguồn nào bên ngoài mô-đun đó.

3

Private

Hạn chế việc sử dụng một thực thể đối với tệp nguồn xác định của chính nó. Quyền truy cập riêng tư đóng vai trò để ẩn các chi tiết triển khai của một chức năng mã cụ thể.

Cú pháp

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Kiểm soát truy cập cho các loại chức năng

Một số hàm có thể có các đối số được khai báo bên trong hàm mà không có bất kỳ giá trị trả về nào. Chương trình sau đây khai báo a và b là các đối số của hàm sum (). Bên trong chính hàm các giá trị cho các đối số a và b được chuyển bằng cách gọi hàm sum () và các giá trị của nó được in ra, do đó loại bỏ các giá trị trả về. Để đặt kiểu trả về của hàm là riêng tư, hãy khai báo mức truy cập tổng thể của hàm với công cụ sửa đổi riêng.

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

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:

30 20
50 40
30 24

Kiểm soát truy cập cho các kiểu liệt kê

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
   
}

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 Marks are: 98,97,95

Phép liệt kê trong ngôn ngữ Swift 4 tự động nhận cùng một mức truy cập cho các trường hợp riêng lẻ của một phép liệt kê. Hãy xem xét ví dụ để truy cập vào tên sinh viên và các điểm được bảo mật trong ba môn học, tên liệt kê được khai báo là sinh viên và các thành viên có mặt trong lớp enum là tên thuộc kiểu dữ liệu chuỗi, các dấu được biểu diễn dưới dạng mark1, mark2 và mark3 của kiểu dữ liệu Integer. Để truy cập tên học sinh hoặc điểm họ đã ghi. Bây giờ, trường hợp chuyển đổi sẽ in tên học sinh nếu khối trường hợp đó được thực thi nếu không, nó sẽ in các dấu được bảo mật bởi học sinh. Nếu cả hai điều kiện không thành công, khối mặc định sẽ được thực thi.

Kiểm soát truy cập cho các lớp con

Swift 4 cho phép người dùng phân lớp bất kỳ lớp nào có thể được truy cập trong ngữ cảnh truy cập hiện tại. Một lớp con không thể có mức truy cập cao hơn lớp cha của nó. Người dùng bị hạn chế viết một lớp con công khai của lớp cha bên trong.

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}

internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.printIt()

let tennisinstance = tennis()
tennisinstance.printIt()

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:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Kiểm soát truy cập cho Hằng số, biến, thuộc tính và chỉ số con

Không thể định nghĩa hằng số, biến hoặc thuộc tính Swift 4 là public hơn kiểu của nó. Việc ghi tài sản công cộng với kiểu tài sản riêng là không hợp lệ. Tương tự, một chỉ số con không thể công khai hơn chỉ mục hoặc kiểu trả về của nó.

Khi một hằng số, biến, thuộc tính hoặc chỉ số con sử dụng kiểu private, thì hằng số, biến, thuộc tính hoặc chỉ số con cũng phải được đánh dấu là private -

private var privateInstance = SomePrivateClass()

Người nhận và Người định cư

Getters và setters cho hằng số, biến, thuộc tính và chỉ số con tự động nhận cùng mức truy cập như hằng số, biến, thuộc tính hoặc chỉ số con mà chúng thuộc về.

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

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:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Kiểm soát truy cập cho Trình khởi tạo và Trình khởi tạo mặc định

Trình khởi tạo tùy chỉnh có thể được chỉ định cấp truy cập nhỏ hơn hoặc bằng loại mà chúng khởi tạo. Bộ khởi tạo bắt buộc phải có cùng mức truy cập với lớp mà nó thuộc về. Các loại tham số của trình khởi tạo không được riêng tư hơn cấp truy cập của chính trình khởi tạo.

Để khai báo mỗi và mọi lớp con của từ khóa khởi tạo 'bắt buộc' cần phải được xác định trước hàm init ().

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

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
30
10

Trình khởi tạo mặc định có cùng mức truy cập với kiểu mà nó khởi tạo, trừ khi kiểu đó được định nghĩa là công khai. Khi khởi tạo mặc định được xác định là công khai, nó được coi là nội bộ. Khi người dùng cần một kiểu công khai có thể khởi tạo được bằng bộ khởi tạo không đối số trong một mô-đun khác, hãy cung cấp rõ ràng một bộ khởi tạo không đối số công khai như một phần định nghĩa của kiểu.

Kiểm soát truy cập cho các giao thức

Khi chúng ta xác định một giao thức mới để kế thừa các chức năng từ một giao thức hiện có, cả hai đều phải được khai báo các mức truy cập giống nhau để kế thừa các thuộc tính của nhau. Kiểm soát truy cập Swift 4 sẽ không cho phép người dùng xác định giao thức 'công khai' kế thừa từ giao thức 'nội bộ'.

public protocol tcpprotocol {
   init(no1: Int)
}
public 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

Kiểm soát truy cập cho các tiện ích mở rộng

Swift 4 không cho phép người dùng cung cấp công cụ sửa đổi mức truy cập rõ ràng cho một tiện ích mở rộng khi người dùng sử dụng tiện ích mở rộng đó để thêm sự tuân thủ giao thức. Mức truy cập mặc định cho việc triển khai từng yêu cầu giao thức trong tiện ích mở rộng được cung cấp mức truy cập giao thức riêng.

Kiểm soát truy cập cho Generics

Generics cho phép người dùng chỉ định mức truy cập tối thiểu để truy cập các ràng buộc kiểu trên các tham số kiểu của nó.

public struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

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:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Kiểm soát truy cập cho loại bí danh

Người dùng có thể xác định bí danh loại để xử lý các loại kiểm soát truy cập riêng biệt. Người dùng có thể xác định cùng một cấp độ truy cập hoặc các cấp độ truy cập khác nhau. Khi bí danh kiểu là 'riêng tư', các thành viên liên kết của nó có thể được khai báo là 'riêng tư, nội bộ của kiểu công khai'. Khi loại bí danh là công khai, các thành viên không được đặt bí danh là tên 'nội bộ' hoặc 'riêng tư'

Bất kỳ loại bí danh nào bạn xác định đều được coi là các loại riêng biệt cho mục đích kiểm soát truy cập. Bí danh kiểu có thể có cấp độ truy cập nhỏ hơn hoặc bằng cấp độ truy cập của kiểu bí danh. Ví dụ: bí danh kiểu riêng tư có thể bí danh là kiểu riêng tư, nội bộ hoặc công khai, nhưng bí danh kiểu công khai không thể bí danh là kiểu nội bộ hoặc riêng tư.

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
   C1: Container, C2: Container
   where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
   (someContainer: C1, anotherContainer: C2) -> Bool {
   
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

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:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Mã hóa và giải mã Swift

Swift 4 giới thiệu một Codable Giao thức, cho phép bạn tuần tự hóa và hủy tuần tự hóa các kiểu dữ liệu tùy chỉnh mà không cần viết bất kỳ mã đặc biệt nào - và không phải lo lắng về việc mất các loại giá trị của bạn.

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

Lưu ý rằng Langauage đang tuân thủ Giao thức có thể mã hóa. Bây giờ chúng ta sẽ chuyển nó thành Biểu diễn dữ liệu Json bằng một dòng đơn giản.

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift sẽ tự động mã hóa tất cả các giá trị bên trong kiểu dữ liệu của bạn.

Bạn có thể giải mã dữ liệu bằng chức năng Bộ giải mã như

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

Cả JSONEncoder và đối tác danh sách thuộc tính PropertyListEncoder của nó đều có rất nhiều tùy chọn để tùy chỉnh cách chúng hoạt động.