Swift - การควบคุมการเข้าถึง

ในการ จำกัด การเข้าถึงบล็อกรหัสโมดูลและสิ่งที่เป็นนามธรรมทำได้ผ่านการควบคุมการเข้าถึง คลาสโครงสร้างและการแจงนับสามารถเข้าถึงได้ตามคุณสมบัติวิธีการตัวเริ่มต้นและตัวห้อยโดยกลไกการควบคุมการเข้าถึง ค่าคงที่ตัวแปรและฟังก์ชันในโปรโตคอลถูก จำกัด และอนุญาตให้เข้าถึงได้ทั้งแบบโกลบอลและโลคัลผ่านการควบคุมการเข้าถึง การควบคุมการเข้าถึงที่ใช้กับคุณสมบัติประเภทและฟังก์ชันสามารถเรียกว่า 'เอนทิตี'

รูปแบบการควบคุมการเข้าถึงจะขึ้นอยู่กับโมดูลและไฟล์ต้นทาง

โมดูลถูกกำหนดให้เป็นหน่วยเดียวของการแจกจ่ายรหัสและสามารถนำเข้าได้โดยใช้คำสำคัญ 'นำเข้า' ซอร์สไฟล์ถูกกำหนดให้เป็นไฟล์ซอร์สโค้ดเดียวที่มีอยู่ในโมดูลเพื่อเข้าถึงประเภทและฟังก์ชันต่างๆ

ระดับการเข้าถึงที่แตกต่างกันสามระดับมีให้โดยภาษา Swift 4 เป็นการเข้าถึงแบบสาธารณะภายในและแบบส่วนตัว

ส. เลขที่ ระดับการเข้าถึงและคำจำกัดความ
1

Public

เปิดใช้งานเอนทิตีที่จะประมวลผลด้วยในซอร์สไฟล์ใด ๆ จากโมดูลที่กำหนดซึ่งเป็นซอร์สไฟล์จากโมดูลอื่นที่อิมพอร์ตโมดูลการกำหนด

2

Internal

เปิดใช้งานเอนทิตีที่จะใช้ภายในซอร์สไฟล์ใด ๆ จากโมดูลการกำหนดของพวกเขา แต่ไม่ใช่ในซอร์สไฟล์ใด ๆ นอกโมดูลนั้น

3

Private

จำกัด การใช้เอนทิตีเฉพาะไฟล์ต้นทางที่กำหนดเอง การเข้าถึงแบบส่วนตัวมีบทบาทในการซ่อนรายละเอียดการใช้งานของฟังก์ชันโค้ดเฉพาะ

ไวยากรณ์

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

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

การควบคุมการเข้าถึงสำหรับประเภทฟังก์ชัน

บางฟังก์ชันอาจมีการประกาศอาร์กิวเมนต์ภายในฟังก์ชันโดยไม่มีค่าส่งกลับ โปรแกรมต่อไปนี้ประกาศ a และ b เป็นอาร์กิวเมนต์ของฟังก์ชัน sum () ภายในฟังก์ชันเองค่าสำหรับอาร์กิวเมนต์ a และ b จะถูกส่งผ่านโดยการเรียกใช้ฟังก์ชันการเรียก sum () และค่าของฟังก์ชันจะถูกพิมพ์ออกมาเพื่อกำจัดค่าที่ส่งคืน ในการกำหนดให้ประเภทการส่งคืนของฟังก์ชันเป็นส่วนตัวให้ประกาศระดับการเข้าถึงโดยรวมของฟังก์ชันด้วยตัวปรับแต่งส่วนตัว

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)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

30 20
50 40
30 24

การควบคุมการเข้าถึงสำหรับประเภทการแจงนับ

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).")
   
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student Marks are: 98,97,95

การแจงนับในภาษา Swift 4 จะได้รับระดับการเข้าถึงเดียวกันโดยอัตโนมัติสำหรับแต่ละกรณีของการแจงนับ ตัวอย่างเช่นในการเข้าถึงชื่อนักเรียนและเครื่องหมายที่ปลอดภัยในชื่อการแจงนับสามวิชาถูกประกาศว่าเป็นนักเรียนและสมาชิกที่อยู่ในคลาส enum เป็นชื่อที่อยู่ในประเภทข้อมูลสตริงเครื่องหมายจะแสดงเป็น mark1, mark2 และ mark3 ของประเภทข้อมูลจำนวนเต็ม ในการเข้าถึงชื่อนักเรียนหรือเครื่องหมายที่พวกเขาได้คะแนน ตอนนี้เคสสวิตช์จะพิมพ์ชื่อนักเรียนหากบล็อกเคสนั้นถูกดำเนินการมิฉะนั้นจะพิมพ์เครื่องหมายที่นักเรียนปลอดภัย หากเงื่อนไขทั้งสองล้มเหลวบล็อกเริ่มต้นจะดำเนินการ

การควบคุมการเข้าถึงสำหรับคลาสย่อย

Swift 4 อนุญาตให้ผู้ใช้ย่อยคลาสใดก็ได้ที่สามารถเข้าถึงได้ในบริบทการเข้าถึงปัจจุบัน คลาสย่อยไม่สามารถมีระดับการเข้าถึงที่สูงกว่าคลาสระดับสูงได้ ผู้ใช้ถูก จำกัด ไม่ให้เขียนคลาสย่อยสาธารณะของซูเปอร์คลาสภายใน

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()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Welcome to Swift Super Class
Welcome to Swift Sub Class

การควบคุมการเข้าถึงสำหรับค่าคงที่ตัวแปรคุณสมบัติและตัวห้อย

ไม่สามารถกำหนดค่าคงที่ตัวแปรหรือคุณสมบัติของ Swift 4 เป็นสาธารณะเกินประเภทได้ ไม่สามารถเขียนทรัพย์สินสาธารณะด้วยประเภทส่วนตัวได้ ในทำนองเดียวกันตัวห้อยต้องไม่เป็นสาธารณะมากกว่าดัชนีหรือประเภทการส่งคืน

เมื่อค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยใช้ประเภทไพรเวตค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยจะต้องถูกทำเครื่องหมายเป็นส่วนตัวด้วย -

private var privateInstance = SomePrivateClass()

Getters และ Setters

ตัวรับและตัวตั้งค่าสำหรับค่าคงที่ตัวแปรคุณสมบัติและตัวห้อยจะได้รับระดับการเข้าถึงเดียวกับค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยโดยอัตโนมัติ

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

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

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

การควบคุมการเข้าถึงสำหรับตัวเริ่มต้นและตัวเริ่มต้นเริ่มต้น

ผู้เริ่มต้นที่กำหนดเองสามารถกำหนดระดับการเข้าถึงที่น้อยกว่าหรือเท่ากับประเภทที่เริ่มต้นได้ ตัวเริ่มต้นที่จำเป็นต้องมีระดับการเข้าถึงเดียวกันกับคลาสที่เป็นของ ประเภทของพารามิเตอร์ของ initializer ต้องไม่เป็นส่วนตัวมากกว่าระดับการเข้าถึงของ initializer

ในการประกาศแต่ละคลาสย่อยของคีย์เวิร์ด 'required' initialize จะต้องกำหนดไว้ก่อนฟังก์ชัน 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()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
30
10

initializer เริ่มต้นมีระดับการเข้าถึงเดียวกับประเภทที่เริ่มต้นเว้นแต่ว่าประเภทนั้นจะถูกกำหนดให้เป็นสาธารณะ เมื่อกำหนดค่าเริ่มต้นเริ่มต้นเป็นสาธารณะจะถือว่าเป็นการภายใน เมื่อผู้ใช้ต้องการชนิดสาธารณะเพื่อเตรียมใช้งานได้ด้วยตัวเริ่มต้นที่ไม่มีอาร์กิวเมนต์ในโมดูลอื่นให้ระบุตัวเริ่มต้นแบบไม่มีอาร์กิวเมนต์สาธารณะอย่างชัดเจนเป็นส่วนหนึ่งของคำจำกัดความของประเภท

การควบคุมการเข้าถึงสำหรับโปรโตคอล

เมื่อเรากำหนดโปรโตคอลใหม่เพื่อสืบทอดฟังก์ชันจากโปรโตคอลที่มีอยู่ทั้งคู่จะต้องได้รับการประกาศระดับการเข้าถึงเดียวกันเพื่อสืบทอดคุณสมบัติของกันและกัน การควบคุมการเข้าถึง Swift 4 จะไม่อนุญาตให้ผู้ใช้กำหนดโปรโตคอล "สาธารณะ" ที่สืบทอดมาจากโปรโตคอล "ภายใน"

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)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

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

การควบคุมการเข้าถึงสำหรับส่วนขยาย

Swift 4 ไม่อนุญาตให้ผู้ใช้จัดเตรียมตัวปรับระดับการเข้าถึงอย่างชัดเจนสำหรับส่วนขยายเมื่อผู้ใช้ใช้ส่วนขยายนั้นเพื่อเพิ่มความสอดคล้องของโปรโตคอล ระดับการเข้าถึงเริ่มต้นสำหรับการดำเนินการตามข้อกำหนดของโปรโตคอลแต่ละรายการภายในส่วนขยายนั้นมาพร้อมกับระดับการเข้าถึงโปรโตคอลของตนเอง

การควบคุมการเข้าถึงสำหรับ Generics

Generics อนุญาตให้ผู้ใช้ระบุระดับการเข้าถึงขั้นต่ำเพื่อเข้าถึงข้อ จำกัด ประเภทบนพารามิเตอร์ประเภท

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()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

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

การควบคุมการเข้าถึงสำหรับนามแฝงประเภท

ผู้ใช้สามารถกำหนดชนิดนามแฝงเพื่อรักษาประเภทการควบคุมการเข้าถึงที่แตกต่างกัน ผู้ใช้สามารถกำหนดระดับการเข้าถึงเดียวกันหรือระดับการเข้าถึงที่แตกต่างกันได้ เมื่อนามแฝงประเภทเป็น 'ส่วนตัว' สมาชิกที่เกี่ยวข้องสามารถประกาศเป็น 'ส่วนตัวภายในประเภทสาธารณะ' เมื่อชื่อนามแฝงเป็นแบบสาธารณะสมาชิกจะไม่สามารถใช้นามแฝงเป็นชื่อ "ภายใน" หรือ "ส่วนตัว" ได้

นามแฝงประเภทใด ๆ ที่คุณกำหนดจะถือว่าเป็นประเภทที่แตกต่างกันเพื่อวัตถุประสงค์ในการควบคุมการเข้าถึง นามแฝงประเภทสามารถมีระดับการเข้าถึงน้อยกว่าหรือเท่ากับระดับการเข้าถึงของนามแฝงประเภท ตัวอย่างเช่นนามแฝงประเภทส่วนตัวสามารถใช้แทนประเภทส่วนตัวภายในหรือประเภทสาธารณะได้ แต่นามแฝงประเภทสาธารณะไม่สามารถใช้แทนประเภทภายในหรือประเภทส่วนตัวได้

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)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

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

การเข้ารหัสและถอดรหัสอย่างรวดเร็ว

Swift 4 เปิดตัวใหม่ Codable Protocol ช่วยให้คุณสามารถทำให้เป็นอนุกรมและ De-serialize ประเภทข้อมูลที่กำหนดเองได้โดยไม่ต้องเขียนโค้ดพิเศษใด ๆ และไม่ต้องกังวลว่าจะสูญเสียประเภทค่าของคุณ

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

สังเกตว่า Langauage เป็นไปตามโปรโตคอล Codable ตอนนี้เราจะแปลงเป็น Json Data Representation โดยใช้บรรทัดเดียว

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

Swift จะเข้ารหัสค่าทั้งหมดภายในชนิดข้อมูลของคุณโดยอัตโนมัติ

คุณสามารถถอดรหัสข้อมูลโดยใช้ฟังก์ชันตัวถอดรหัสเช่น

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

ทั้ง JSONEncoder และรายการคุณสมบัติคู่กัน PropertyListEncoder มีตัวเลือกมากมายสำหรับการปรับแต่งวิธีการทำงาน