본문 바로가기

카테고리 없음

iOS 프로그래밍 실무 4주차

 

add(x:y:)
add(first:second:)
add(_:_:)
add(_:with:)

 

각 함수의 시그니처(함수명과 자료형)는 다음과 같습니다.

swift

func add(x: Int, y: Int) -> Int
  • 외부 매개변수명: x, y
  • 내부 매개변수명: x, y
  • 반환형: Int

swift

func add(first x: Int, second y: Int) -> Int
  • 외부 매개변수명: first, second
  • 내부 매개변수명: x, y
  • 반환형: Int

swift

func add(_ x: Int, _ y: Int) -> Int
  • 외부 매개변수명 생략 (언더바 _로 표시)
  • 내부 매개변수명: x, y
  • 반환형: Int

swift

func add(_ x: Int, with y: Int) -> Int
  • 첫 번째 매개변수 외부 매개변수명 생략(_)
  • 두 번째 매개변수 외부 매개변수명: with
  • 내부 매개변수명: x, y
  • 반환형: Int

정리하면, 모든 함수 이름은 add이고 모두 Int 타입 파라미터 두 개를 받아서 Int 타입을 반환합니다.

 

 

 

numberOfRowsInSection

 

func tableView(
    _ tableView: UITableView,
    numberOfRowsInSection section: Int
) -> Int

 

이 함수의 함수명과 자료형

✅ 함수명

  • tableView(_:numberOfRowsInSection:)

👉 Swift에서는 **외부 매개변수명(argument label)**까지 포함해서 함수명을 구성합니다.


✅ 함수의 자료형 (타입)

(UITableView, Int) -> Int
 

 


✅ 의미 풀이

  • 입력:
    • UITableView (첫 번째 파라미터, _라서 호출 시 이름 생략)
    • Int (section)
  • 출력:
    • Int (해당 섹션의 row 개수)

🔍 추가 설명

이 함수는 UIKit
UITableViewDataSource 프로토콜에 포함된 메서드입니다.

즉, 테이블뷰가 "이 섹션에 몇 개의 셀이 있냐?"라고 물을 때 호출되는 함수입니다.

 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return cell }

✅ 함수명

  • tableView(_:cellForRowAt:)

👉 외부 매개변수명까지 포함된 완전한 함수 시그니처 이름입니다.


✅ 함수의 자료형 (타입)

(UITableView, IndexPath) -> UITableViewCell
 

✅ 의미 풀이

  • 입력:
    • UITableView (어떤 테이블뷰인지)
    • IndexPath (몇 번째 섹션/행인지)
  • 출력:
    • UITableViewCell (해당 위치에 표시할 셀)

🔍 추가 설명

이 함수 역시
UIKit
UITableViewDataSource에 포함된 필수 메서드입니다.

 

디폴드 매개변수(argument)

->

**디폴트 매개변수(Default Parameter)**는
함수를 호출할 때 값을 생략하면 자동으로 기본값이 사용되는 매개변수를 의미합니다.


✅ 개념 이해

함수를 만들 때 미리 값을 지정해두면:

  • 호출 시 값을 넘기면 → 그 값 사용
  • 호출 시 생략하면 → 기본값(default) 사용

✅ Swift 예시

 
func greet(name: String = "Guest") {
print("Hello, \(name)!")
}
 

호출 방법

 
greet(name: "Alice") // Hello, Alice!
greet() // Hello, Guest!
 

👉 name을 안 넘기면 "Guest"가 자동으로 들어갑니다.


✅ 매개변수가 여러 개인 경우

 
func power(base: Int, exponent: Int = 2) -> Int {
return Int(pow(Double(base), Double(exponent)))
}
 
 
power(base: 3, exponent: 3) // 27
power(base: 3) // 9 (exponent 기본값 2 사용)
 

✅ 왜 사용할까?

  • 함수 호출을 더 간단하게 만들기 위해
  • 자주 쓰는 값을 기본값으로 설정하기 위해
  • API를 더 유연하게 만들기 위해

✅ 한 줄 정리

👉 디폴트 매개변수 = 값을 안 넣으면 자동으로 대신 들어가는 미리 정해둔 값

 

print문

func print( _ items: Any..., separator: String = " ", terminator: String = "\n" )

 

String | Apple Developer Documentation

A Unicode string value that is a collection of characters.

developer.apple.com

1️⃣ 함수명

  • print

👉 실제로는 다음과 같은 시그니처 이름을 가집니다:

print(_:separator:terminator:)
 

2️⃣ 첫 번째 매개변수: 가변 매개변수 + 외부 이름 생략

 
_ items: Any...
 

✔ 의미

  • _ : 외부 매개변수명 생략 (호출할 때 이름 안 씀)
  • items : 내부에서 사용할 이름
  • Any : 어떤 타입이든 받을 수 있음
  • ... : 가변 매개변수 (Variadic Parameter)

✔ 결과

👉 여러 개의 값을 한 번에 받을 수 있음

 
print("A", "B", 10, true)
 

👉 내부적으로는:

 
items = ["A", "B", 10, true]
 

3️⃣ 두 번째 매개변수: 기본값 있는 매개변수

 
separator: String = " "
 

✔ 의미

  • 출력 값들 사이에 넣을 문자열
  • 기본값: " " (공백)

✔ 사용 예

 
print("A", "B", "C") // A B C
print("A", "B", "C", separator: "-") // A-B-C
 

4️⃣ 세 번째 매개변수: 기본값 있는 매개변수

 
terminator: String = "\n"
 

✔ 의미

  • 출력 끝에 붙는 문자열
  • 기본값: 줄바꿈 (\n)

✔ 사용 예

 
print("Hello") // Hello + 줄바꿈
print("Hello", terminator: "") // Hello (줄바꿈 없음)
 

5️⃣ 함수의 리턴 타입

👉 생략되어 있음 → Void (아무것도 반환하지 않음)


6️⃣ 함수 타입 (자료형)

이 함수는 정확히 쓰면 조금 특이합니다:

(Any..., String, String) -> Void
 

하지만 가변 매개변수는 타입 시스템에서 배열처럼 취급되므로 개념적으로는:

([Any], String, String) -> Void
 

🔍 핵심 문법 포인트 정리

문법 요소의미
_ 외부 매개변수명 생략
Any 모든 타입 허용
... 가변 매개변수
= 값 디폴트 매개변수
반환 타입 생략 Void

✅ 한 줄 핵심 요약

👉 print는
**"여러 값을 받아서(separator로 이어붙이고 terminator를 붙여 출력하는 함수"**입니다.

 

 

 

✅ 1급 객체의 조건 (핵심 3가지)

1️⃣ 변수에 저장할 수 있다

 
let x = 10
let f = someFunction
 

👉 값처럼 변수에 담을 수 있어야 합니다.


2️⃣ 함수의 매개변수로 전달할 수 있다

 
func doSomething(fn: () -> Void) {
fn()
}
 

👉 함수를 다른 함수에 넘길 수 있음


3️⃣ 함수의 반환값으로 사용할 수 있다

 
func makeFunction() -> () -> Void {
return { print("Hello") }
}
 

👉 함수가 함수를 만들어서 돌려줄 수도 있음


✅ 대표적인 예: 함수(Function)

많은 현대 언어에서 함수는 1급 객체입니다.

예를 들어 Swift에서는:

 
func add(a: Int, b: Int) -> Int {
return a + b
}

let myFunc = add
print(myFunc(2, 3)) // 5
 

👉 함수 자체를 값처럼 다룰 수 있음


✅ 왜 중요한가?

이 개념이 있으면:

  • 함수를 값처럼 전달 가능 → 콜백, 클로저
  • 코드를 더 유연하게 구성 가능
  • 함수형 프로그래밍 가능

✅ 쉽게 비유하면

  • 일반 값: 숫자, 문자열 → 자유롭게 이동 가능
  • 1급 객체: 숫자처럼 똑같이 다룰 수 있는 대상

👉 즉,
“변수에 담고, 넘기고, 돌려줄 수 있으면 = 1급 객체”


✅ 한 줄 정리

👉 1급 객체 = 프로그램 안에서 ‘값처럼’ 완전히 자유롭게 사용할 수 있는 대상

 

 

func up(num: Int) -> Int {

    return num + 1

}

func down(num: Int) -> Int {

    return num - 1

}

let toUp = up

//Swift 함수는 일급 객체로, 변수나 상수에 저장할 수 있음 print(up(num:10))

print(up(num:10))

print(down(num:5))

print(toUp(5))

//주의 : argument label인 (num:) 안 씀

// 함수를 변수에 할당하면 argument label(num:)을 생략해야 함

let toDown = down

toDown(3)

print(toDown(3))

 

 

toUp 자료형

 

add1의 자료형

 

위에는 일반 함수 호출

아래는 클로저로 호출을 하면 아규먼트레이블이 필요하지 않다.

🔥 핵심 비교 (진짜 중요)

구분일반 함수클로저
이름 있음 (add) 없음
저장 직접 사용 변수에 저장
타입 (Int, Int) -> Int 동일
호출 add(x:y:) add1(3,5)

 

 

func mul(a: Int, b: Int) -> Int {

    return a * b

}

let multiply = {(a: Int, b: Int) -> Int in

    return a * b

}

print(mul(a:10, b:20))

print(multiply(10, 20))

 

let add = {(a: Int, b: Int) -> Int in

    return a + b

}

print(add(10, 20))

 

 

func mul(a: Int, b: Int) -> Int {

    return a * b

}

 

 

let multiply = { (a: Int, b: Int) -> Int in

    return a * b

}

 

 

print(mul(a: 10, b: 20))

print(multiply(10, 20))

 

 

let add = { (a: Int, b: Int) -> Int in

    return a + b

}

 

print(add(10, 20))

 

 

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {

    return cal(x, y)

}

 

var result = math(x: 10, y: 20, cal: add)

print(result)

 

result = math(x: 10, y: 20, cal: multiply)

print(result)

 

 

result = math(x: 10, y: 20, cal: { (a: Int, b: Int) -> Int in

    return a + b

})

print(result)

 

 

result = math(x: 10, y: 20) { (a: Int, b: Int) -> Int in

    return a + b

}

print(result)

중요(시험)

클로저의 축약 표현

 

1. 클로저 기본 정의 및 사용

swift

let multiply = {(val1: Int, val2: Int) -> Int in
    return val1 * val2
}
var result = multiply(10, 20)
print(result) // 200
  • multiply라는 클로저 변수에 두 개의 Int를 받아 곱셈 결과를 Int로 반환하는 클로저를 할당했습니다.
  • 변수처럼 호출 가능하며, 10과 20을 곱해 200을 출력합니다.

2. add 클로저 정의 및 호출

swift

let add = {(val1: Int, val2: Int) -> Int in
    return val1 + val2
}
result = add(10, 20)
print(result) // 30
  •  Int를 더하는 클로저를 add라는 상수에 할당했습니다.
  • add(10, 20) 호출 시 30이 출력됩니다.

3. 함수에 클로저 타입 매개변수 전달하기

swift

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
    return cal(x, y)
}
  • math라는 함수는 x, y라는 Int 두 개와 (Int, Int) -> Int 타입의 클로저를 매개변수로 받습니다.
  • 이 클로저 cal에 x, y를 전달하여 계산한 결과를 반환합니다.

swift

result = math(x: 10, y: 20, cal: add)
print(result) // 30

result = math(x: 10, y: 20, cal: multiply)
print(result) // 200
  • 외부에서 정의한 add, multiply 클로저를 인자로 넘겨 함수 내에서 실행할 수 있습니다.

4. 클로저를 매개변수로 직접 작성하는 다양한 방법

swift

result = math(x: 10, y: 20, cal: {(val1: Int, val2: Int) -> Int in
    return val1 + val2
})
print(result) // 30
  • 클로저를 함수 호출 시점에 직접 정의해서 넘겨주는 방식입니다.

5. Trailing Closure (후행 클로저) 문법

swift

result = math(x: 10, y: 20) {(val1: Int, val2: Int) -> Int in
    return val1 + val2
}
print(result) // 30
  • 함수의 마지막 매개변수가 클로저라면 괄호 밖에 클로저 본문을 작성할 수 있는 문법입니다.

6. 매개변수 이름 생략과 축약 인자명 사용

swift

result = math(x: 10, y: 20, cal: {
    return $0 + $1
})
print(result) // 30
  • 클로저 매개변수 이름 없이 $0과 $1 같은 축약 인자명으로 바로 접근 가능합니다.
  • return 키워드도 생략 가능하며, 한 줄이면 마지막 표현식이 반환값이 됩니다.

swift

result = math(x: 10, y: 20) { $0 + $1 }
print(result) // 30
  • 가장 간결한 형태로 클로저를 작성한 예입니다.

요약

  • 클로저는 함수처럼 동작하는 코드 블록이며, 변수나 상수에 할당 가능합니다.
  • 함수 매개변수로 클로저를 넘겨 원하는 시점에 실행할 수 있습니다.
  • Swift에서는 클로저를 생략 가능 매개변수 이름, 축약 인자명, 후행 클로저 문법 등 여러 방법으로 간결하게 작성할 수 있어 가독성과 편의성이 뛰어납니다.

 

오류발생

 

수정후

class Man{

    var age : Int = 0

    var weight : Double

} //오류 나는 이유?

->

age와 wegiht는 프로퍼티(값)이 있어야 한다.

 

class Man{

var age : Int? //옵셔널 변수는 nil로 자동 초기화

var weight : Double? //옵셔널 변수는 nil로 자동 초기화

}

->

옵션널  (!,?)으로 만들면 자동으로 값이 nil 로 들어간다 

 

class Man{

    var age : Int

    var weight : Double

    init(){ //initializer로 초기화

        age = 1

        weight = 3.5

    }

}

kim이 초기화 되지 않음

1.

class Man{

    var age : Int = 1

    var weight : Double = 3.5

    func display(){

        print("나이=\(age), 몸무게=\(weight)")

    }

}

var kim : Man = Man()//클래스 이름(), ()함수호출

var x : Int = 10

print(kim.age)

 

//var kim : Man = Man()

//kim.display() //인스턴스 메서드는 인스턴스가 호출

//print(kim.age)

 

2. itit 사용

class Man{

    var age : Int = 1

    var weight : Double = 3.5

    func display(){

        print("나이=\(age), 몸무게=\(weight)")

    }

    init(){}

}

var kim : Man = Man()

print(kim.age)

default initializer(디폴트 생성자)란?

디폴트 생성자란, Swift가 클래스나 구조체의 모든 저장 속성이 기본값을 가지고 있을 때 자동으로 만들어 주는 매개변수가 없는 생성자입니다.

  • 역할: 객체를 만들 때 속성을 기본값으로 초기화
  • 형태: 매개변수 없는 init()

즉, 우리가 직접 init()를 안 만들어도 Swift가 자동으로 만들어 줍니다.


예시

 
class Man {
var age: Int = 1
var weight: Double = 3.5
func display() {
print("나이=\(age), 몸무게=\(weight)")
}
}

let kim = Man() // Swift가 자동으로 만들어준 디폴트 생성자 호출
print(kim.age) // 1
kim.display() // 나이=1, 몸무게=3.5
 
  • Man()에서 ()가 바로 디폴트 생성자 호출입니다.
  • Swift가 자동으로 만들어준 init() 덕분에 별도로 정의하지 않아도 객체를 만들 수 있습니다.

2️⃣ 디폴트 생성자와 위 코드 연결

앞서 보여주신 코드에서는 이렇게 있었죠:

 
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(){} // 직접 만든 생성자
}

var kim: Man = Man() // 여기가 핵심
 
  • init(){}를 직접 만들어도, 매개변수 없는 생성자라면 디폴트 생성자와 똑같은 역할을 합니다.
  • 즉, 위 코드에서 Man()는:
  1. 메모리 할당
  2. age = 1, weight = 3.5 초기화
  3. init() 실행 → 특별한 코드 없음
  • Swift가 자동으로 만들어주는 디폴트 생성자와 기능상 동일

3️⃣ 요약

구분의미
디폴트 생성자 매개변수 없는 생성자, 속성이 모두 기본값을 가지면 Swift가 자동 생성
init() 개발자가 직접 만든 생성자
Man() 객체를 생성하는 표현, 디폴트 생성자 또는 직접 만든 init() 호출

🔹 핵심 연결점

  • Man()의 () = 디폴트 생성자 호출
  • 디폴트 생성자 덕분에 매개변수 없이 객체 생성 가능
  • 직접 init()를 정의하면, Swift가 자동으로 만들어주는 디폴트 생성자는 덮어쓰여집니다.

\

class Man{

    var age : Int = 1

    var weight : Double = 3.5

    func display(){

        print("나이=\(age), 몸무게=\(weight)")

    }

    init(age: Int, weight : Double){

        self.age = age //self.을 만드시 써야 함

        //매개변수 age값을 프로퍼티 age에 대입

        self.weight = weight

    }

}

var kim : Man = Man(age:10, weight:20.5)

kim.display()

 

->

class Man{

    var age : Int

    var weight : Double 

    func display(){

        print("나이=\(age), 몸무게=\(weight)")

    }

    init(age: Int, weight : Double){

        self.age = age //self.을 만드시 써야 함

        //매개변수 age값을 프로퍼티 age에 대입

        self.weight = weight

    }

}

var kim : Man = Man(age:10, weight:20.5)

kim.display()

초기값을 생략

 

-------------------------------------------------------------------------------------------------------------------

Man의 값을 상속

 

override생략시 오류발생

오버라이드(Override)란?

오버라이드란:

상속받은 부모 클래스(슈퍼클래스)의 메서드
자식 클래스(서브클래스)에서 재정의해서 바꾸는 것

즉, 부모 클래스의 기능을 그대로 쓰는 대신, 자식 클래스에서 새로운 동작을 정의할 수 있는 기능입니다.


2️⃣ Swift 예제

 
// 부모 클래스
class Animal {
func speak() {
print("동물이 소리를 냅니다.")
}
}

// 자식 클래스
class Dog: Animal {
override func speak() {
print("멍멍!")
}
}

// 사용
let a = Animal()
a.speak() // 동물이 소리를 냅니다.

let d = Dog()
d.speak() // 멍멍!
 

3️⃣ 코드 분석

  1. 부모 클래스 정의
 
class Animal {
func speak() {
print("동물이 소리를 냅니다.")
}
}
 
  • Animal 클래스는 speak()라는 메서드를 가지고 있습니다.

  1. 자식 클래스 정의 및 오버라이드
 
class Dog: Animal {
override func speak() {
print("멍멍!")
}
}
 
  • Dog 클래스가 Animal을 상속(: Animal) 받습니다.
  • 부모 클래스의 speak()를 재정의하려면 반드시 override 키워드를 사용해야 합니다.
  • 이렇게 하면 Dog 객체가 speak()를 호출할 때 부모의 코드 대신 자식 코드가 실행됩니다.

  1. 오버라이드의 특징
  • 부모 메서드와 같은 이름, 같은 매개변수, 같은 반환형이어야 합니다.
  • override 키워드는 부모 메서드를 재정의한다는 것을 컴파일러에게 알려주는 역할
  • 만약 override 없이 이름이 같으면, 컴파일 오류가 발생합니다.

4️⃣ 부모 메서드도 함께 사용하기

 
class Cat: Animal {
override func speak() {
super.speak() // 부모 클래스 메서드도 호출
print("야옹!")
}
}

let c = Cat()
c.speak()
 

출력:

동물이 소리를 냅니다.
야옹!
 
  • super.speak() → 부모 클래스의 기능을 그대로 사용
  • 그 뒤에 자식 클래스의 동작을 추가 가능

5️⃣ 한 줄 요약

오버라이드 = 부모 클래스의 메서드를 자식 클래스에서 재정의해서 원하는 동작으로 바꾸는 것

-> 부모와 같은 이름의 함수앞에 붙힌다

지정 생성자(Designated Initializer)란?

->모든 프로퍼티를 다 초기화 시켜주는 생성자(중요시험)

Designated Initializer는 클래스에서 모든 속성을 초기화하고 객체를 완전히 준비시키는 기본 생성자를 말합니다.

  • 클래스에서 가장 “중심”이 되는 생성자
  • 반드시 **모든 저장 속성(stored property)**를 초기화해야 함
  • 다른 초기화 메서드(Convenience Initializer)를 호출할 수도 있음

Swift에서는 지정 생성자를 통해 객체를 안전하게 초기화하는 것이 핵심입니다.


2️⃣ 코드에서 지정 생성자 예시

 
class Man {
var age: Int
var weight: Double

func display() {
print("나이=\(age), 몸무게=\(weight)")
}

init(yourAge: Int, yourWeight: Double) {
age = yourAge
weight = yourWeight
} // 이것이 지정 생성자
}
 
  • init(yourAge: Int, yourWeight: Double)
    → 모든 속성(age, weight)을 초기화하고, 객체를 완전히 준비시킴
  • 지정 생성자는 클래스에서 꼭 하나 이상 있어야 객체 생성 가능

3️⃣ 왜 var kim: Man = Man()는 오류일까?

 
// var kim : Man = Man() //오류
 
  • 이제 속성 age와 weight에 기본값이 없음
  • Swift는 init()처럼 매개변수 없는 디폴트 생성자를 자동으로 만들지 못합니다.
  • 반드시 모든 속성을 초기화하는 지정 생성자를 사용해야 함
 
var kim: Man = Man(yourAge: 10, yourWeight: 20.5) // 정상
kim.display()
 
  • yourAge와 yourWeight를 넘겨주어 속성을 초기화
  • 그래서 객체 생성 가능 ✅

4️⃣ 디폴트 생성자 vs 지정 생성자

구분디폴트 생성자지정 생성자(Designated)
자동 생성 속성에 기본값이 있을 때 없음, 직접 정의 필요
매개변수 없음 필요에 따라 정의 가능
목적 간단히 객체 생성 모든 속성을 안전하게 초기화

5️⃣ 한 줄 핵심 정리

지정 생성자 = 클래스 속성을 모두 초기화하고, 객체를 완전히 준비시키는 “주 생성자”

 

 

1문재 정도 시험

 

Double 구조체

매소드,프로퍼티

 

extension Double {

    var squared : Double {

        return self * self

    }

}

let myValue: Double = 4.0

print(myValue.squared)

print(2.0.squared) //Double형 값에도 .으로 바로 사용 가능

print(myValue.isZero)

<Extension이란?>

 
extension Double {
var squared: Double {
return self * self
}
}
 
  • extension Double { ... }
    → 기존 타입 Double에 새로운 기능을 추가하는 것
  • Swift에서는 기존 클래스, 구조체, 열거형, 기본 타입(Int, Double 등)도 확장 가능
  • 여기서는 **계산 속성(Computed Property) squared**를 추가했습니다

2️⃣ 계산 속성(Computed Property) squared

 
var squared: Double {
return self * self
}
 
  • self → 현재 값을 의미 (Double 타입 자신)
  • self * self → 제곱 연산
  • 사용 예:
 
let myValue: Double = 4.0
print(myValue.squared) // 16.0
 

👉 기존 Double 타입에 제곱 기능을 바로 사용할 수 있습니다.


3️⃣ 다양한 사용 예

 
print(2.0.squared) // 4.0
print(myValue.isZero) // false
 
  • 2.0.squared → 2 * 2 = 4
  • myValue.isZero → Double 타입이 원래 가지고 있는 기본 속성 isZero도 그대로 사용 가능
    → Extension으로 새 기능을 추가해도 기존 기능 손상 없음

4️⃣ 핵심 포인트

  1. Extension
    • 기존 타입에 기능을 추가 가능
    • 기존 코드를 수정하지 않아도 됨
  2. 계산 속성
    • 값을 저장하지 않고, 접근할 때마다 계산된 값을 반환
    • squared처럼 읽기 전용(get-only) 속성 가능
  3. self
    • Extension 안에서는 현재 값을 의미

5️⃣ 한 줄 요약

이 코드는 Double 타입을 확장해서 .squared 계산 속성을 추가하고, 기존 기능(isZero)과 함께 사용할 수 있음을 보여줍니다.

 

xtension을 사용하는 이유

Extension은 기존 타입에 새로운 기능을 추가할 수 있는 방법입니다.

  • 기존 코드를 수정하지 않고 기능 추가 가능
  • 타입을 상속하지 않고도 메서드/속성 추가 가능
  • 코드 재사용성, 가독성, 유지보수성을 높일 수 있음

Extension 장점

  1. 기존 코드 안전
    • 기존 Double 코드를 건드리지 않음
    • 버그 위험 최소화
  2. 재사용성
    • 여러 곳에서 squared 기능을 반복 작성하지 않고 재사용 가능
  3. 가독성 향상
    • x.squared → 한눈에 의미 파악 가능
    • x * x보다 훨씬 직관적
  4. 기존 타입과 자연스럽게 통합
    • 기존 isZero, rounded 같은 속성/메서드와 같이 사용 가능

Extension을 사용하는 이유

Extension은 기존 타입에 새로운 기능을 추가할 수 있는 방법입니다.

  • 기존 코드를 수정하지 않고 기능 추가 가능
  • 타입을 상속하지 않고도 메서드/속성 추가 가능
  • 코드 재사용성, 가독성, 유지보수성을 높일 수 있음

🔹 예시로 이해

기존에 Double 타입이 있습니다:

 
let x: Double = 4.0
 
  • Swift 기본 Double에는 squared 같은 제곱 기능이 없음
  • 매번 x * x라고 쓰기 귀찮음
  • 이럴 때 Extension을 쓰면:
 
extension Double {
var squared: Double {
return self * self
}
}
 
  • 이제 4.0.squared처럼 코드가 직관적이 됩니다
  • 원래 Double 타입 자체는 그대로 유지됨

2️⃣ Extension 장점

  1. 기존 코드 안전
    • 기존 Double 코드를 건드리지 않음
    • 버그 위험 최소화
  2. 재사용성
    • 여러 곳에서 squared 기능을 반복 작성하지 않고 재사용 가능
  3. 가독성 향상
    • x.squared → 한눈에 의미 파악 가능
    • x * x보다 훨씬 직관적
  4. 기존 타입과 자연스럽게 통합
    • 기존 isZero, rounded 같은 속성/메서드와 같이 사용 가능
 
print(myValue.squared) // 새 기능
print(myValue.isZero) // 기존 기능
 

ccess Modifier란?(2문제 시험)

**Access Modifier(접근 제어자)**란:

클래스, 구조체, 변수, 함수, 속성 등 프로그램 요소의 접근 범위를 제한하는 키워드

즉, 어디서 그 코드에 접근할 수 있는지를 제어하는 장치입니다.


🔹 왜 필요할까?

  • 데이터 보호 → 외부에서 마음대로 접근하지 못하도록
  • 캡슐화(Encapsulation) → 객체지향 설계 원칙
  • 코드 유지보수 → 내부 구현을 바꿔도 외부 코드에 영향 최소화

2️⃣ Swift에서 접근 제어자 종류

접근 제어자설명사용 예
open 모듈 안팎에서 상속과 오버라이드 모두 가능 open class MyClass { ... }
public 모듈 외부에서도 사용 가능, 상속은 모듈 내만 가능 public var name: String
internal (기본값) 같은 모듈 내에서만 접근 가능 var age: Int
fileprivate 같은 파일 내에서만 접근 가능 fileprivate func helper() { ... }
private 같은 타입(클래스/구조체) 내에서만 접근 가능 private var secret: String

3️⃣ 예시로 이해

 
class Person {
private var ssn: String // 외부에서 접근 불가
var name: String // 기본 internal
public var email: String // 외부 모듈에서도 접근 가능

init(name: String, ssn: String, email: String) {
self.name = name
self.ssn = ssn
self.email = email
}
}

let p = Person(name: "Kim", ssn: "123-45-6789", email: "kim@example.com")
print(p.name) // 가능
print(p.email) // 가능
// print(p.ssn) // 오류! private이므로 접근 불가
 
  • ssn은 private → 외부에서 접근 불가
  • name은 internal → 같은 모듈에서 접근 가능
  • email은 public → 다른 모듈에서도 접근 가능

4️⃣ 핵심 포인트

  1. 외부 접근을 제한해 안전하게 보호
  2. 클래스, 구조체, 변수, 메서드, 속성 등 거의 모든 요소에 적용 가능
  3. Swift 기본 접근 수준은 internal

5️⃣ 한 줄 요약

Access Modifier = 코드의 접근 범위를 제한해 안전성과 캡슐화를 보장하는 키워드

 
 

 

언어접근 제어자설명클래스 접근멤버(속성/메서드) 접근
C 없음 C는 클래스가 없고 구조체(struct)만 있어서 접근 제어자가 없음 N/A N/A
C++ private 같은 클래스 안에서만 접근 가능 가능 가능
  protected 같은 클래스 + 상속받은 클래스에서 접근 가능 가능 가능
  public 어디서든 접근 가능 가능 가능
C# private 같은 클래스 안에서만 접근 가능 가능 가능
  protected 같은 클래스 + 상속 클래스에서 접근 가능 가능 가능
  internal 같은 어셈블리(Assembly) 안에서 접근 가능 가능 가능
  protected internal 상속 클래스 + 같은 어셈블리에서 접근 가능 가능 가능
  public 어디서든 접근 가능 가능 가능
Java private 같은 클래스 안에서만 접근 가능 가능 가능
  (default, 아무 modifier 없음) 같은 패키지(package) 안에서 접근 가능 가능 가능
  protected 같은 패키지 + 상속 클래스에서 접근 가능 가능 가능
  public 어디서든 접근 가능 가능 가능

🔹 추가 설명

  1. C는 클래스가 없어서 접근 제어자가 없음
  2. **C++**에서는 private, protected, public만 있음
  3. **C#**에는 internal과 protected internal이 추가되어 모듈/어셈블리 수준 제어 가능
  4. Javadefault 접근 수준이 있음 (아무 modifier 없으면 같은 패키지에서만 접근 가능)

기본 접근 속성

 

1. swift에서는 internal이 기본접근속성

2. 최근 새로 만들어진 옵션 package

접근 제어자접근 범위상속/오버라이드사용 가능 위치패키지 관점
open 모듈 안/밖 ✅ 가능 클래스, 클래스 멤버 다른 패키지에서도 상속/오버라이드 가능
public 모듈 안/밖 ❌ 상속/오버라이드 제한 (모듈 내에서만 가능) 클래스, 구조체, 열거형, 변수, 메서드 다른 패키지에서도 접근 가능, 상속/오버라이드는 모듈 내부만 가능
internal (기본값) 같은 모듈/패키지 안 ✅ 가능 모든 타입/멤버 패키지 외부에서는 접근 불가
fileprivate 같은 파일 ✅ 가능 (같은 파일 안) 모든 타입/멤버 파일 외부에서는 접근 불가
private 같은 타입 ✅ 가능 (같은 타입 안) 모든 타입/멤버 타입 외부에서는 접근 불가

🔹 패키지 관점 요약

  1. Swift에서 패키지 = 모듈(Module)
  2. internal은 같은 패키지 안에서만 접근 가능, 패키지 외부에서는 불가
  3. public과 open은 패키지 외부에서도 접근 가능
    • open은 상속/오버라이드까지 허용
    • public은 상속/오버라이드는 모듈 내부만 가능

🔹 접근 범위 시각화

private < fileprivate < internal < public < open
타입 내 < 파일 내 < 모듈/패키지 내 < 모듈 외부 접근 < 모듈 외부 + 상속/오버라이드

package가 추가