Swift-제네릭

Swift 4 언어는 유연하고 재사용 가능한 함수 및 유형을 작성하는 '일반'기능을 제공합니다. 제네릭은 중복을 방지하고 추상화를 제공하는 데 사용됩니다. Swift 4 표준 라이브러리는 제네릭 코드로 빌드됩니다. Swift 4s 'Arrays'및 'Dictionary'유형은 제네릭 컬렉션에 속합니다. 배열과 사전의 도움으로 배열은 'Int'값과 'String'값 또는 기타 유형을 보유하도록 정의됩니다.

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}

var numb1 = 100
var numb2 = 200

print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

일반 함수 : 유형 매개 변수

일반 함수를 사용하여 'Int'또는 'String'과 같은 데이터 유형에 액세스 할 수 있습니다.

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

함수 exchange ()는 위의 프로그램에서 설명한 값을 바꾸는 데 사용되며 <T>는 유형 매개 변수로 사용됩니다. 처음으로 'Int'값을 반환하기 위해 함수 exchange ()가 호출되고 함수 exchange ()에 대한 두 번째 호출은 'String'값을 반환합니다. 쉼표로 구분 된 꺾쇠 괄호 안에 여러 매개 변수 유형이 포함될 수 있습니다.

유형 매개 변수는 보유하는 유형 매개 변수의 목적을 알기 위해 사용자가 정의한 이름으로 지정됩니다. Swift 4는 일반 유형 매개 변수 이름으로 <T>를 제공합니다. 그러나 배열 및 사전과 같은 유형 매개 변수는 '사전'유형에 속함을 식별하기 위해 키, 값으로 이름을 지정할 수도 있습니다.

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]

일반 유형 확장

항목의 상단을 알 수 있도록 스택 속성을 확장하는 것은 '확장'키워드에 포함되어 있습니다.

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)

extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

유형 제약

Swift 4 언어는 '유형 제약'이 유형 매개 변수가 특정 클래스에서 상속되는지 여부를 지정하거나 프로토콜 준수 표준을 보장하도록 허용합니다.

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

관련 유형

Swift 4를 사용하면 'relatedtype'키워드로 프로토콜 정의 내에서 관련 유형을 선언 할 수 있습니다.

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<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]
   }
}
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)

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Where 절

유형 제약을 통해 사용자는 일반 함수 또는 유형과 관련된 유형 매개 변수에 대한 요구 사항을 정의 할 수 있습니다. 연관된 유형에 대한 요구 사항을 정의하기 위해 'where'절이 유형 매개 변수 목록의 일부로 선언됩니다. 'where'키워드는 유형 매개 변수 목록 바로 뒤에 관련 유형의 제약 조건, 유형 및 관련 유형 간의 동등 관계가 뒤 따릅니다.

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]