Generics(제네릭)
2023. 2. 27. 23:43ㆍ개발/Swift
1. 제네릭 정의
• Write Codes that works for multiple types and specify requirements for those types.
• 여러타입에서 사용 가능한 타입.(범용 타입이라고 봐도 무방함.)
2. 제네릭의 필요성
• 제네릭을 한번 선언하면 사용 할 때마다 타입을 지정할 수 있어서 코드를 반복구현하지 않을 수 있음.
3. 제네릭 문법
• Fuction
• 타입파라미터를 <T>로 지정하고, 파라미터에서 타입으로 사용한다.
• <T: 제약조건> 형식으로 제네릭 타입을 제약할 수 있다.(프로토콜 제약, 클래스 제약 두가지)
func printData<T: Equatable>(_ data: T) { print(data) }
printData(8) //"8"
• Struct, Class
• 타입파라미터를 <T>로 지정하고, 파라미터에서 타입으로 사용한다.
• Struct, Class 내 메서드는 타입파라미터를 따로 지정하지 않고 바로 사용한다.
struct Fruits<T> {
var fruit: T
func printFavoriteFruits(_ item: T) { print("나는 \(fruit)&\(item)를 좋아해.") } //Struct, Class 내 메서드는 타입파라미터를 따로 지정하지 않고 바로 사용한다.
}
var fruits = Fruits(fruit: "사과")
fruits.printFavoriteFruits("바나나") //"나는 딸기&바나나를 좋아해"
class Fruits<T> {
var fruit: T
init(_ fruit: T) {
self.fruit = fruit
}
func printFavoriteFruits(_ item: T) { print("나는 \(fruit)&\(item)를 좋아해.") } //Struct, Class 내 메서드는 타입파라미터를 따로 지정하지 않고 바로 사용한다.
}
var fruits = Fruits("딸기")
fruits.printFavoriteFruits("바나나") //"나는 딸기&바나나를 좋아해"
• Enum
• 타입파라미터를 <T>로 지정하고, 파라미터에서 타입으로 사용한다.
• case명 뒤에 (T)를 표시해서 타입으로 사용한다.
enum Fruits<T> {
case apple
case banana
case orange(T) //case명 뒤에 (T)를 표시해서 타입으로 사용한다.
}
var fruit = Fruits.orange("오렌지")
var countOrange = Fruits.orange(3)
print(fruit) //orange("오렌지")
print(countOrange) //orange(3)
• Extension
• 확장에서는 타입파라미터 명시 없이 사용한다.
class Fruits<T> {
var fruit: T
init(_ fruit: T) {
self.fruit = fruit
}
func printFavoriteFruits(_ item: T) { print("나는 \(fruit)&\(item)를 좋아해.") }
}
extension Fruits { //확장에서는 타입파라미터 명시 없이 사용한다.
func printNumberOneFruit() { print("그 중에 최고는 \(fruit)!") }
}
var fruits = Fruits("딸기")
fruits.printFavoriteFruits("바나나") //나는 딸기&바나나를 좋아해.
fruits.printNumberOneFruit() //그 중에 최고는 딸기!
4. 프로토콜에서 제네릭 문법의 사용
• 연관타입 지정(다른 자료형처럼 <T> 대신 associatedtype T 사용)
• 타입을 Int로 정의했기 때문에 이 클래스에서 T는 Int이다.(typealias 생략하고 바로 타입사용해도 됨)
protocol Fruits {
associatedtype T: Equatable //연관타입 지정(다른 자료형처럼 <T> 대신 associatedtype T 사용)
var count: T { get }
func estimateValuationPrice(_ count: T)
}
class Apple: Fruits {
typealias T = Int //타입을 Int로 정의했기 때문에 이 클래스에서 T는 Int이다.(typealias 생략하고 바로 타입사용해도 됨)
var count: T = 100
func estimateValuationPrice(_ size: Int) {
print("이 과일의 가치는 \(count * size)원 입니다.")
}
}
var apple = Apple()
apple.estimateValuationPrice(30) //"이 과일의 가치는 3000원 입니다."