열거형
enum Compass {
case North
case South
case East
case West
}
print(Compass.North) //North
var x : Compass //Compass형 인스턴스 x
x = Compass.West
print(x, type(of:x)) // West Compass
x = .East
print(x) //East
// 열거형명을 추론할 수 있는 상황에서 열거형 생략 가능
Swift에서 .의 기능
Swift에서 .
(점) 연산자는 주로 다음과 같은 용도로 사용됩니다:
- 속성 접근 (Property Access):
객체의 속성이나 메서드에 접근할 때 사용합니다.
class Person { var name: String init(name: String) { self.name = name } } let person = Person(name: "John") print(person.name) // "John"
여기서
person.name
은Person
객체의name
속성에 접근하는 예입니다. - 메서드 호출 (Method Call):
객체의 메서드를 호출할 때 사용합니다.
class Calculator { func add(a: Int, b: Int) -> Int { return a + b } } let calculator = Calculator() let result = calculator.add(a: 5, b: 3) print(result) // 8
여기서
calculator.add(a:b:)
는Calculator
객체의add
메서드를 호출하는 예입니다. - 네임스페이스 접근 (Namespace Access):
모듈이나 타입 내의 네임스페이스에 접근할 때 사용합니다.
import Foundation let currentDate = Date() let formatter = DateFormatter() formatter.dateStyle = .medium let dateString = formatter.string(from: currentDate) print(dateString)
여기서
DateFormatter
의dateStyle
속성에.medium
을 할당하는 예입니다. 이는DateFormatter.Style.medium
의 축약형입니다. - 열거형의 케이스 접근 (Enum Case Access):
열거형의 특정 케이스에 접근할 때 사용합니다.
enum Direction { case north case south case east case west } let direction = Direction.north switch direction { case .north: print("North") case .south: print("South") case .east: print("East") case .west: print("West") }
여기서
Direction
열거형의north
케이스에 접근하는 예입니다.
구조체
struct Resolution { //구조체 정의
var width = 1024 //프로퍼티
var height = 768
}
let myComputer = Resolution() //인스턴스 생성
print(myComputer.width) //프로퍼티 접근 1024
// class
class Resolution { //구조체 정의
var width = 1024 //프로퍼티
var height = 768
init(width : Int, height : Int){
self.width = width
self.height = height
}
}
let myComputer = Resolution.init(width:100, height:50) //인스턴스 생성 .init 생략 가능 보통 생략
print(myComputer.width) //프로퍼티 접근
Class 안에 구조체
struct Resolution {
var width = 1024
var height = 768
}
class VideoMode {
var resolution = Resolution()
var frameRate = 0.0
}
let myVideo = VideoMode()
print(myVideo.resolution.width)
Class vs Struct vs Enum
상속을 하려면 class를 사용해야한다. (구조체는 상속 불가)
class Human {
var age : Int = 1
}
var kim = Human()
var lee = kim //값 타입
print(kim.age, lee.age)
lee.age = 20
print(kim.age, lee.age)
kim.age = 30
print(kim.age, lee.age)
/*
1 1
20 20
30 30
참조 타입은 복사할 때 주소르 복사해서 한 데이터의 reference가 2개 생김
*/
struct Human {
var age : Int = 1
}
var kim = Human()
var lee = kim //값 타입
print(kim.age, lee.age)
lee.age = 20
print(kim.age, lee.age)
kim.age = 30
print(kim.age, lee.age)
/*
1 1
1 20
30 20
값 타입은 복사할 때 새로운 데이터가 하나 더 생김s
*/
Generic
func myPrint<T>(a: T, b: T) {
print(b,a)
}
myPrint(a:1,b:2)
myPrint(a:2.5,b:3.5)
myPrint(a:"cmu",b:"good")
// 처음부터 자료형을 정하지 않고 실행할 때 자료형을 찍어내주는 기법을 Generic이라고 한다.
괄호들의 역할
() : 함수나 메소드를 호출할 때 사용 {} : 블럭을 만들 때 사용 [] : 배열, 리스트를 만들 때 사용 <> : Generic을 활용할 때 사용 (자료형을 나중에 결정하고 싶을 때)
Generic을 사용하는 언어들
제네릭(Generic)은 다양한 데이터 타입을 처리할 수 있는 코드 구조를 작성할 때 사용되는 강력한 기능입니다. 제네릭을 지원하는 대표적인 프로그래밍 언어들을 예시와 함께 소개하겠습니다.
- Java:
Java는 제네릭을 사용하여 타입 안정성을 보장합니다.
public class Box<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } Box<Integer> integerBox = new Box<>(); integerBox.set(10); Integer value = integerBox.get();
- C#:
C#에서도 제네릭 타입을 지원하여 타입 안전성과 코드 재사용성을 높입니다.
public class Box<T> { private T value; public void Set(T value) { this.value = value; } public T Get() { return value; } } Box<int> integerBox = new Box<int>(); integerBox.Set(10); int value = integerBox.Get();
- C++:
C++에서는 템플릿을 통해 제네릭 프로그래밍을 구현합니다.
template <typename T> T add(T a, T b) { return a + b; } int result = add<int>(3, 4); double result2 = add<double>(3.0, 4.0);
- Swift:
Swift는 제네릭을 사용하여 타입 안정성을 강화합니다.
func swap<T>(_ a: inout T, _ b: inout T) { let temp = a a = b b = temp } var x = 5 var y = 10 swap(&x, &y)
- TypeScript:
TypeScript는 JavaScript의 슈퍼셋으로, 제네릭 타입을 지원합니다.
function identity<T>(arg: T): T { return arg; } let output = identity<string>("myString"); let output2 = identity<number>(42);
- Kotlin:
Kotlin도 제네릭 타입을 지원하여 더욱 유연한 코드를 작성할 수 있게 합니다.
class Box<T>(t: T) { var value = t } val box: Box<Int> = Box(1)
- Go:
Go는 1.18부터 제네릭을 공식 지원하기 시작했습니다.
func MapKeys[K comparable, V any](m map[K]V) []K { r := make([]K, 0, len(m)) for k := range m { r = append(r, k) } return r } m := map[string]int{"foo": 1, "bar": 2} keys := MapKeys(m)
- Rust:
Rust는 제네릭을 통해 다양한 타입의 데이터를 처리할 수 있습니다.
fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest } let number_list = vec![34, 50, 25, 100, 65]; let result = largest(&number_list);
- Dart:
Dart는 제네릭을 사용하여 타입 안전성을 높입니다.
class Box<T> { T value; Box(this.value); } var box = Box<int>(123);
- Scala:
Scala는 제네릭을 사용하여 더욱 유연한 타입 시스템을 제공합니다.
class Box[T](var value: T) val intBox = new Box[Int](10) val stringBox = new Box[String]("Hello")
이 밖에도 제네릭을 지원하는 언어는 많지만, 위 언어들은 제네릭 기능을 대표적으로 잘 활용하는 언어들입니다. 제네릭을 통해 코드의 재사용성을 높이고, 타입 안정성을 보장할 수 있습니다.
출처
- Smile Han의 iOS 프로그래밍 실무, 한성현(출판 예정), PPT로 제공
- Do it! 스위프트로 아이폰 앱 만들기 입문(개정 7판)(이지스퍼블리싱,송호정, 이범근, 2023.1)
- 핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍(제이펍, 닐 스미스, 2023.12)
- https://www.techotopia.com/index.php/IOS_iPhone_iPad_eBooks
- 스위프트 프로그래밍(Swift 5) 3판(한빛미디어, 야곰, 2019.10)
- 꼼꼼한 재은 씨의 스위프트 기본편 (루비페이퍼, 이재은, 2018.05)
- 꼼꼼한 재은 씨의 스위프트 실전편 (Swift) (루비페이퍼, 이재은, 2018.08)
- 꼼꼼한 재은 씨의 Swift 문법편 (루비페이퍼, 이재은, 2017.12)