써니쿠키의 IOS 개발일기
[swift] 제네릭? generic 본문
어쩌다 공부하게 되었는가...?
엊그제 드루와방에서 코드짜다가 다른 동기들의 토론에 제너릭 얘기가 나왔는데 또 나만 몰라...🥹서 공부해보자했다 ㅎㅎㅎ허허허 배움되지유.. 덕분에 삼항연산자도 배웠다구유~
똑똑이들 최고 👍🏻 옆에서 많이배웁니다 ㅎㅎ
❓ 함수의 매개변수의 타입으로 Int, String, Double등 모든 타입을 받고싶을때는?
Generic 타입으로 받을 수있다. 어메이징. 제네릭이 대체 뭔데 ??
❓ 근데 Any타입이 있는데 Generic ??
?? 이유를 찾는중.... 누가좀 알려주세요 ㅎㅎㅎㅎㅎ
일단 아래예제에서는 Any타입으로 바꿔줄시 값들도 Any타입이여야만 가능하다고 뜨긴하는데.......... inout 파라미터를 써서그런건가?
📝 공식문서 generic 설명
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
- 요약하자면
제네릭 코드를 사용하면 모든 타입에서 작동 가능한 함수 및 generic타입을 만들 수 있는데 이렇게 되면 중복을 피해서 코드를 쓸 수 있다는 것! - 중복을 피한다 는게 뭐냐면 예를들어 Int타입을 매개변수로 받는 함수가 있는데 double타입을 받는경우도 필요하면 똑같은 내용의 코드를 매개변수 타입만 바꿔서 써줘야한다. 이 때 제네릭을 이용하면 하나의 함수로 Int도 받고 double도 받을 수 있는 것!!
🔥 예제를 봐야만 이해가 되는 generic
예제에 앞서 예제의 코드는 사실 스위프트에서 자체 코드인 swap(::) 함수를 사용하면 된다네요
1. generic이 아닌 일반함수 일 때
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
// 매개변수 a,b가 함수안에서 값이 변하므로 in-out매개변수를 사용했고
//함수의 내용은 a와 b의 값을 바꾸는 내용입니다.
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt는 \(someInt), anotherInt 는 지금 \(anotherInt)")
// 출력 "someInt는 107, anotherInt 는 지금 3"
지금 위의 함수는 Int 값에만 사용할 수 있는 함수이다.
혹시 String 값 또는 Double 값을 교환하려면swapTwoStrings(_:_:)
및 swapTwoDoubles(_:_:)
같이
같은기능을 하는 함수를 타입만 바꿔서 더 만들어줘야하는 번거로움!
이런 번거로움을 해소하고자 쓸 수 있는게 generic이다.
2. Generic 함수사용
이제 한개의 함수로 여러타입을 받게 generic함수를 생성해보자!
generic 함수를 생성하려면 일반함수에서 두 부분을 신경써주면 된다
뭐가 다른지 찾아보자..!
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
//Int를 받을 수 있다
var someInt2 = 30
var anotherInt2 = 1070
swapTwoValues(&someInt2, &anotherInt2)
print("someInt2는 \(someInt2), anotherInt2 는 지금 \(anotherInt2)")
//someInt2는 1070, anotherInt2 는 지금 30
//String도 받을 수 있다!
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
print("someString는 \(someString), anotherString 는 지금 \(anotherString)")
//someString는 world, anotherString 는 지금 hello
- 매개변수의 타입으로 T
제네릭함수에서는 실제 타입인 Int, String, Double 대신 자리 표시자(placeholder)타입 이름을 사용하는데 이 경우엔 T를 사용했다.
이 T는 함수가 호출될때에 타입(Int,String,..)이 '결정'되는것으로
함수가 호출 될 때 마다 결정된다고 보면 된다!- 함수명 +
함수명 뒤에 꺾쇠 괄호로 타입 이름을 알려준다.
-> swapTwoValues꺽새괄호는 T가 함수 내에서 쓸 타입 이름임을 Swift에 알려주어서 Swift는 T라는 실제 유형을 찾지 않게해준다.
- 함수명 +
- 'T'라는 문자는 바꿀 수 있고 upper camel case로 써주면된다.
(예를 들면 S, MyTypeParameter 등...) - ⚠️ 이때, Swift는안전한 언어이며 타입에 굉장히 민감하기 때문에 파라미터에서 a와 b는 반드시 타입이 같아야한다. a값이 Int고 b값이 String으로 들어가면 서로 바꿀 수 없어서 컴파일 에러가 난다.
좀 더 알아보자!
Type Parameters
꺾쇠 괄호 안에 여러 유형 매개변수 이름을 쉼표로 구분하여 작성하여 둘 이상의 유형 매개변수를 제공할 수도 있다. ex) <T, S>
Type Naming
대부분의 타입매개변수에서는 의미를 알 수 있는 이름이 좋다
(예를들면 Dictionary<Key, Value>의 Key 및 Value, Array의 Element와 같다.)
그러나 의미 있는 관계가 없는 경우 위의 swapTwoValues(::) 함수에서 T와 같이 T, U, V와 같은 단일 문자를 사용하여 이름을 지정하는 것이 일반적이다. 다만 CamelUpper을 유지해야한다.
제네릭함수 외에도 제네릭 타입
도 있고 타입제약
도 있다 공부해보자💪🏻
참고문서: 공식문서 Swift language Guide
'swift, Ios' 카테고리의 다른 글
ios - Auto Layout (1) (0) | 2022.09.06 |
---|---|
[swift]열거형 연관된 값(Associated Values) (0) | 2022.08.30 |
[swift] static 은 언제쓰지??? 타입메서드 / 타입프로퍼티 (0) | 2022.08.25 |
[swift] 재귀함수 (0) | 2022.08.24 |
[swift] enumerated(), forEach() (0) | 2022.08.23 |