오늘 한 일 / 배운점
- iOS 앱개발 입문 팀 프로젝트 과제
- 8/16 9:00 팀 회의 / 코드리뷰
- 8/18 19:00 보충학습 (HG튜터님) : 확장
과제
- iOS 앱개발 입문 팀 프로젝트 과제
느낀점
오늘은 보충수업때 확장(Extension)에 대한 개념을 배웠다
상속 - Person -> Developer, Doctor : 타입을 새로 만드는 것. 데이터를 추가하고 함수를 변형시켜 사용(수직적) 확장 - 현재 존재하는 타입에 함수를 추가하여 사용(수평적)
확장은 기존 타입에 새로운 기능을 추가하거나 확장하는 것을 의미한다. 상속과 달리 수직적인 확장이 아닌 수평적인 확장이라고 할 수 있으며
확장은 클래스, 구조체, 열거형, 프로토콜에 적용할 수 있으며,
Int
, String
, Date
등 이미 구현된 타입에 추가 기능을 편리하게 구현할 수 있다.
아래는 기존 Dog
클래스에 growl
이라는 기능을 추가하는 확장 예시다
class Dog {
let age = 3
let breed = "진돗개"
func bark() {
print("멍멍")
}
}
extension Dog {
func growl() {
print("으르렁")
}
}
let dog = Dog()
dog.growl()
저장 속성은 반드시 클래스 선언부에 있어야 하며,
deinit
등 일부 기능은 확장에 추가할 수 없다.
반면 계산 속성은 확장에서도 정의 가능!
또한, 확장을 활용하여 코드를 기능별로 더 깔끔하게 나눌 수도 있는데
아래는 Developer
클래스의 study
와 play
기능을 기능별로 확장하여 코드를 조직화한 예시다
class Developer: Person {
var language = "Swift"
override func work() {
print("개발한다")
}
func study() {
print("\(language)를 공부한다")
}
}
extension Developer {
func play() {
print("게임한다")
}
}
이런식으로 기능별로 extension을 활용해서 코드를 가독성있게 나눌수도 있다
또한, 기존 타입을 extension으로 확장하여 유용한 기능을 추가할 수도 있는데 아래는 정수, 문자열, 날짜 타입에 대한 확장을 통해 각각의 기능을 추가한 예시다.
// 1
extension Int {
var square: Int {
self * self
}
}
3.square // 결과 : 9
// 2
extension String {
var starCovered: String {
return "***" + self + "***"
}
}
"hello".starCovered // 결과 : "***hello***"
// 3
extension Date {
var formatted: String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(identifier: TimeZone.current.identifier)!
return formatter.string(from: self)
}
}
Date().formatted // 결과 : "2023-08-18 19:21:20"
이렇게 date를 String으로 변환한다던지
이런 자주쓰이는것도 확장을 활용하면 유용하게 사용가능하다
또 주의사항으로는
extension String {
func makeStarString() {
self = "***" + self + "***" // immutable에러가 뜸
}
}
extension String {
mutating func makeStarString() {
self = "***" + self + "***"
}
}
var str = "hello"
str.makeStarString() // ***hello***
str // ***hello***
구조체(struct)내부의 저장속성을 변경할때에는 반드시 mutating
키워드 붙여아 한다
subscript
extension String {
subscript(idx: Int) -> String? {
guard (0..<count).contains(idx) else {
return nil
}
let target = index(startIndex, offsetBy: idx)
return String(self[target])
}
}
let helloWorld = "Hello world"
helloWorld[0] // "H"
helloWorld[5] // ""
helloWorld[100] // nil
이 부분은 subscript
를 사용하여 문자열 내의 특정 인덱스에 접근하는 방법을 확장을 통해 추가하는 예시이다
※ subscript : array[1] 이런 것 같이 인덱스로 접근할 수 있는 것들
String은 subscript 지원 안하지만 이렇게 만들어서 사용 가능
중첩타입
extension Dog {
enum Spacies{
case maltese
case shihTzu
case pomeranian
}
}
Dog.Species.maltese
Dog.Species.shihTzu
위의 코드에서 보여주는 것처럼, 확장을 통해 클래스 내부에 중첩 타입을 추가하는 방법도 있고
class ViewControllerExample: UIViewController {
}
extension ViewControllerExample: UITableViewDelegate {
}
extension ViewControllerExample: UITableViewDataSource {
}
이런식으로 코드 작성에서 클래스와 확장을 사용하여 코드를 더 구조적이고 가독성 있게 나누어서 사용할 수 있다