Swift-액세스 제어
코드 블록, 모듈 및 추상화에 대한 액세스를 제한하기 위해 액세스 제어를 통해 수행됩니다. 클래스, 구조 및 열거는 액세스 제어 메커니즘을 통해 속성, 메서드, 이니셜 라이저 및 첨자에 따라 액세스 할 수 있습니다. 프로토콜의 상수, 변수 및 함수는 제한되며 액세스 제어를 통해 전역 및 로컬로 액세스 할 수 있습니다. 속성, 유형 및 기능에 적용된 액세스 제어를 '엔티티'라고 할 수 있습니다.
액세스 제어 모델은 모듈 및 소스 파일을 기반으로합니다.
모듈은 단일 코드 배포 단위로 정의되며 'import'키워드를 사용하여 가져올 수 있습니다. 소스 파일은 여러 유형과 함수에 액세스하기 위해 모듈에있는 단일 소스 코드 파일로 정의됩니다.
Swift 4 언어는 세 가지 액세스 수준을 제공합니다. 공개, 내부 및 비공개 액세스입니다.
S. 아니 | 액세스 수준 및 정의 |
---|---|
1 | Public 정의 모듈을 가져 오는 다른 모듈의 소스 파일 인 정의 모듈의 모든 소스 파일에서 엔티티를 처리 할 수 있습니다. |
2 | Internal 정의 모듈의 모든 소스 파일 내에서 엔티티를 사용할 수 있지만 해당 모듈 외부의 소스 파일에서는 사용할 수 없습니다. |
삼 | Private 엔티티의 사용을 자체 정의 소스 파일로 제한합니다. 개인 액세스는 특정 코드 기능의 구현 세부 사항을 숨기는 역할을합니다. |
통사론
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
기능 유형에 대한 액세스 제어
일부 함수에는 반환 값없이 함수 내에서 선언 된 인수가있을 수 있습니다. 다음 프로그램은 sum () 함수에 대한 인수로 a와 b를 선언합니다. 함수 자체 내에서 인수 a 및 b에 대한 값은 함수 호출 sum ()을 호출하여 전달되고 해당 값이 인쇄되어 반환 값을 제거합니다. 함수의 반환 유형을 비공개로 만들려면 private 한정자를 사용하여 함수의 전체 액세스 수준을 선언합니다.
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)
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
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).")
}
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Student Marks are: 98,97,95
Swift 4 언어의 열거는 열거의 개별 사례에 대해 동일한 액세스 수준을 자동으로받습니다. 예를 들어 세 과목에서 보안 된 학생 이름과 마크에 액세스하는 경우 열거 이름은 student로 선언되고 enum 클래스에있는 멤버는 문자열 데이터 유형에 속하는 이름이며 마크는 Integer 데이터 유형의 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()
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Welcome to Swift Super Class
Welcome to Swift Sub Class
상수, 변수, 속성 및 아래 첨자에 대한 액세스 제어
Swift 4 상수, 변수 또는 속성은 해당 유형보다 공용으로 정의 할 수 없습니다. 전용 유형으로 공용 속성을 작성하는 것은 유효하지 않습니다. 마찬가지로 아래 첨자는 색인 또는 반환 유형보다 더 공개 될 수 없습니다.
상수, 변수, 속성 또는 아래 첨자가 전용 유형을 사용하는 경우 상수, 변수, 속성 또는 아래 첨자도 전용으로 표시되어야합니다.
private var privateInstance = SomePrivateClass()
게터와 세터
상수, 변수, 속성 및 아래 첨자에 대한 게터 및 세터는 이들이 속한 상수, 변수, 속성 또는 아래 첨자와 동일한 액세스 수준을 자동으로받습니다.
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
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
이니셜 라이저 및 기본 이니셜 라이저에 대한 액세스 제어
사용자 지정 이니셜 라이저에는 초기화하는 유형보다 작거나 같은 액세스 수준을 할당 할 수 있습니다. 필수 이니셜 라이저는 자신이 속한 클래스와 동일한 액세스 수준을 가져야합니다. 이니셜 라이저의 매개 변수 유형은 이니셜 라이저의 자체 액세스 수준보다 더 비공개 일 수 없습니다.
initialize 'required'키워드의 모든 하위 클래스를 선언하려면 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()
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
10
30
10
기본 이니셜 라이저는 해당 유형이 public으로 정의되지 않는 한 초기화하는 유형과 동일한 액세스 수준을 갖습니다. 기본 초기화가 공용으로 정의되면 내부로 간주됩니다. 사용자가 다른 모듈의 인수없는 이니셜 라이저를 사용하여 초기화 할 수있는 공용 형식이 필요한 경우 형식 정의의 일부로 공용 형식없는 이니셜 라이저를 명시 적으로 제공하십시오.
프로토콜에 대한 액세스 제어
기존 프로토콜에서 기능을 상속하기 위해 새 프로토콜을 정의 할 때, 둘 다 서로의 속성을 상속하려면 동일한 액세스 수준을 선언해야합니다. 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)")
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
res is: 20
res is: 30
res is: 50
확장에 대한 액세스 제어
Swift 4는 사용자가 프로토콜 준수를 추가하기 위해 해당 확장을 사용할 때 확장에 대한 명시 적 액세스 수준 수정자를 제공하는 것을 허용하지 않습니다. 확장 내의 각 프로토콜 요구 사항 구현에 대한 기본 액세스 수준은 자체 프로토콜 액세스 수준과 함께 제공됩니다.
제네릭에 대한 액세스 제어
제네릭을 사용하면 사용자가 유형 매개 변수에 대한 유형 제약 조건에 액세스하기위한 최소 액세스 수준을 지정할 수 있습니다.
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()
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
유형 별칭에 대한 액세스 제어
사용자는 고유 한 액세스 제어 유형을 처리하기 위해 유형 별명을 정의 할 수 있습니다. 사용자는 동일한 액세스 수준 또는 다른 액세스 수준을 정의 할 수 있습니다. 유형 별칭이 'private'이면 관련 멤버를 'private, internal of public type'으로 선언 할 수 있습니다. 유형 별칭이 공용이면 멤버는 '내부'또는 '개인'이름으로 별칭이 될 수 없습니다.
사용자가 정의하는 모든 유형 별명은 액세스 제어를 위해 고유 한 유형으로 처리됩니다. 유형 별칭은 별칭이 지정된 유형의 액세스 수준보다 작거나 같은 액세스 수준을 가질 수 있습니다. 예를 들어 개인 유형 별칭은 개인, 내부 또는 공용 유형의 별칭을 지정할 수 있지만 공용 유형 별칭은 내부 또는 개인 유형의 별칭을 지정할 수 없습니다.
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)
Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
신속한 인코딩 및 디코딩
Swift 4는 새로운 Codable 프로토콜 : 특별한 코드를 작성하지 않고 값 유형을 잃어 버릴 염려없이 사용자 정의 데이터 유형을 직렬화 및 직렬화 해제 할 수 있습니다.
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 Protocol을 준수합니다. 이제 간단한 한 줄을 사용하여 Json 데이터 표현으로 변환합니다.
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
//Perform some operations on this value.
}
Swift는 데이터 유형 내의 모든 값을 자동으로 인코딩합니다.
Decoder 기능을 사용하여 데이터를 디코딩 할 수 있습니다.
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
//Perform some operations on this value.
}
JSONEncoder 및 해당 속성 목록 대응 PropertyListEncoder에는 작동 방식을 사용자 지정하기위한 많은 옵션이 있습니다.