[iOS-Swift] 클래스와 구조체

TIL 5일 차 - 클래스와 구조체 학습하기

 

1. 클래스와 구조체는 대체 뭐가 다른가?

2. 클래스와 구조체를 활용해 데이터를 구조화하고 효율적으로 관리하기

3. 값 타입(Struct)와 참조 타입(Class)의 차이를 이해하고 적절한 상황에 사용하기

 

클래스(Class)

쉽게 설명하자면 (속성property + 행동 method)을 합쳐놓은 개념.. 붕어빵 틀이다.

이걸 이용해서 붕어빵을 찍어낼수있고 캡슐화로 재사용과 유지보수에도 용이하다.

이 클래스를 배우면 이제 본격적으로 객체지향프로그래밍을 시작한다고 생각하면 된다.

 

// 클래스의 기본 문법

class 클래스이름 {
    var 속성이름: 타입
    init(초기화 할 속성 이름: 이 속성의 타입) {
        self.속성이름 = 속성이름
    }
    func 메서드이름() {
        실행할 코드
    }
}
// 클래스 내의 변수, 상수는 프로퍼티라고 함
// 클래스 내의 함수는 메소드라고 함
//이름,나이 변수와 프린트 메서드 클래스
class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func introduce() {
        print("안녕하세요, 저는 \(name)이고 \(age)살이에요.")
    }
}

let person1 = Person(name: "명수", age: 25)
person1.introduce() // '안녕하세요, 저는 명수이고 25살이에요.'
let person2 = Person(name: "도자캣", age: 29)

// person1과 person2는 서로같은 Person 클래스의 인스턴스이지만 각각 다른 인스턴스이다.

 

 

 

1) 클래스는 구조체와 달리 참조 타입이다.

// 클래스는 참조 타입이다!!!!!!!!!!
let a = Person(name: "명수", age: 56)
let b = a

b.name = "재석"

print(a.name) // 재석 출력 됨
// a의 주소값이 b에게 대입되었으므로 a와 b는 같은 인스턴스를 가리키게 됨

 

2) 상속이 가능하다.

// Student 클래스가 Person을 상속받음
// 부모가 가진 속성과 기능을 재사용 가능하다.
class Student: Person {
    var school: String
    
    init(name: String, age: Int, school: String) {
        self.school = school
        super.init(name: name, age: age)
        // super는 내가 물려받은 부모클래스를 뜻함
        // 부모클래스가 가진 속성도 빼먹지않고 초기화 해주어야 한다.
    }
}

 

 

3) iOS UI는 거의 다 클래스다.

// 화면에 올라가는 UI 객체들
// 생명주기와 상태 공유가 필요하므로 참조타입인 클래스를 사용한다.
let label = UILabel()
let button = UIButton()
let viewController = UIViewController()

 

 

클래스의 초기화

  • class안에서 사용되는 변수와 상수인 프로퍼티에는 default값을 정해줄 수 있음
  • class의 인스턴스를 생성할때는 반드시 초기화를 해줘야 함
  • 모든 프로퍼티에 default값을 제공한다면 init 초기화를 생략할 수 있음
  • 모든 프로퍼티가 Optional인 경우 init 초기화를 생략할 수 있음
  • 초기화를 도와주는 컨비니언스 이니셜라이저(convenience init)를 제공함. 구조체에서는 제공 X

 

초기화의 방법들

 

1. 지정 초기화

class Person {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let person = Person(name: "JH", age: 24)

 

 

2. 기본값 초기화

- 프로퍼티에 기본값을 넣으면 초기화 안 해도 됨

- 하지만 프로퍼티의 기본값이 하나라도 빠진다면 init을 구현해 모든 값을 프로퍼티의 값을 채워야 함

class Person {
    var name: String = "이름없음"
    var age: Int = 0
}

 

 

3. 여러 개의 init 사용

- 여러 가지의 init을 만들면 여러가지 방법으로 class를 초기화할 수 있음

// 지정 초기화
// 일반적인 init

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    init(name: String) {
        self.name = name
        self.age = 0
    }
    
    init() {
        self.name = "이름없음"
        self.age = 24
    }
}

 

 

4. convenience init: 보조 초기화

- 클래스에서만 사용할 수 있는 기능으로 구조체에서는 사용 불가

// 파라미터에 값을 할당하지않고 컨비니언스 이니셜라이즈를 사용할 수 있음

class Person {
    var name: String
    var age: Int
    
    init(name: String, aage: Int) {
        self.name = name
        self.age = age
    }
    
    convenience init(name: String) {
        self.init(name: name, age:0)
    }
}

let person = Person(name: "이름만 입력")
print(person.age) // 0 출력

 

 

+ deinit: 소멸자

- class에서만 사용 가능함

- 사용이 종료된 인스턴스가 메모리에서 해제될 때 자동 호출됨

- 직접 호출은 불가

deinit {
	// 구현부
}

 

 

구조체(Struct)

 

대체 얘는 뭐고 왜 필요하냐!

=> 간단한 데이터 집합을 표현하고 싶을 때 구조체를 사용한다.

=> 값을 복사해서 사용, 즉 독립적인 복사본이 필요한 경우에는 구조체가 적합하다.

 

그냥 즉 프린트기라고 생각하면 된다. 아까 클래스는 집주소를 가져왔다면 구조체는 그 집의 알맹이만 복사해 온 느낌..!

아무리 복사해 와도 그 집의 주인은 그대로임

// 구조체 예제

struct Rectangle {
    var width: Double
    var height: Double
    
    func area() -> Double {
        return width*height
    }
}

let rect1 = Rectangle(width:5.0, height:10.0)
print(rect1.area())
// 50.0 출력

var rect2 = rect1

rect2.width = 20.0
print(rect1.area())
// 50.0 출력

print(rect2.area())
// 200.0 출력

출력 방식이 참조방식인 클래스와는 다르게 값 타입(Value Type)으로 되는 것을 확인할 수 있다.

 

  • 멤버와이즈 이니셜라이저를 제공해 직접 init을 정의하지 않아도 모든 프로퍼티의 초기화를 자동으로 생성해 주는 기능이 있음
  • 메서드에서 프로퍼티를 변경하려면 mutating 키워드를 사용해야 함
  • struct은 값타입이므로 당연히 상속은 불가능함
  • 인스턴스를 let으로 만들면 내부 프로퍼티를 변경할 수 없으므로 프로퍼티를 변경하려면 var로 만들어야 함

 

memberwise init 사용해 초기화하는 법

struct Person {
	var name: String
    var age: Int
    
    // class와 다르게 init을 생성하지않아도 자동으로 됨
}

var person = Person(name: "JH", age: 24)

 

 

지정 초기화

// init을 직접 생성하면 memberwise init이 사용되지 않음

struct Person {
    var name: String = "이름없음"
    var age: Int = 1
    
    init() {
        print("init")
    }
}

Person()
Person(name: "JH") // Error: 멤버와이즈 init 적용 안되었음
Person(age: 24) // Error: 파라미터로 ge만 전달하는 init을 지정 안했으므로 에러
Person(name: "JH", age: 24) // Error: argument passed to call that takes no arguments

 

 

 

함수에 mutating 붙이기 (함수를 사용해 프로퍼티의 값이 변경될 때)

struct Person {
    var name: String
    var age: Int
    
    func introduce() {
        print("안녕하세요 \(name)입니다. 저는 \(age)살 입니다.")
    }
    
    mutating func happyNewYear() {
        age += 1
    }
}

var me = Person(name: "JH", age: 24)
me.age // 24
me.name // 'JH'
me.introduce() // '안녕하세요 JH입니다. 저는 24살 입니다.'
me.happyNewYear()
me.introduce() // '안녕하세요 JH입니다. 저는 25살 입니다.'

 

 

 

 

'iOS  > Swift ' 카테고리의 다른 글

[iOS-Swift] 조건문  (0) 2026.01.06
[iOS-Swift] 기본 데이터 타입  (0) 2026.01.06
[iOS-Swift] 변수와 상수  (0) 2026.01.06
[iOS] 앱 아키텍쳐 기초 (MVC,MVVM)  (0) 2026.01.05
[iOS-Swift] 함수와 클로저, 옵셔널  (1) 2025.12.31