[Swift] 구조체, 클래스, 프로퍼티, 메서드

김상우·2021년 10월 26일
0
post-custom-banner

Keyword

  1. Struct / Class
  2. 프로퍼티 / 메서드
  3. init() / deinit()
  4. 저장 프로퍼티 / 연산 프로퍼티 / 타입 프로퍼티
  5. 프로퍼티 옵저버 - willSet / didSet
  6. Value Type / Reference Type
  7. 구조체와 클래스의 차이점
  8. self 키워드

Swift의 구조체

  • 구조체 형태
struct 구조체 이름{
  프로퍼티, 메서드
}

구조체의 멤버 변수를 프로퍼티, 구조체의 멤버 함수를 메서드라고 한다.

// 구조체
struct User{
    var nickname: String
    var age: Int
    
    func infromation(){
        print("\(nickname) \(age)")
    }
}

// 정의한 구조체를 사용하기 위해서는 인스턴스를 생성해야 한다.
// 인스턴스를 생성한다는 것은 구조체나 클래스를 실제로 사용하기 위해서
// 메모리에 생성하는 것을 말한다.

var user1 = User(nickname: "KSW", age: 26)

user1.nickname
user1.nickname = "BSJ"
user1.nickname

user1.infromation()

Swift의 클래스

  • 클래스 형태
class 클래스 이름 {
  프로퍼티, 메서드
}

예시

// 클래스
class Dog {
    var name: String = ""
    var age: Int = 0
    
    init(){
    }
    
    func information(){
        print("\(name) \(age)")
    }
}

var dog = Dog()
dog.name = "Cloud"
dog.age = 3
dog.name
dog.age
dog.information()

구조체와 비교했을 때 문법이 매우 유사한 것을 알 수 있다.

초기화 구문 Init

  • Initialization
    클래스, 구조체 또는 열거형의 인스턴스를 사용하기 위한 준비 과정
    C++, Java의 생성자 개념

예시

// Init() 활용하기. self 키워드 활용
class User {
    var nickname: String
    var age: Int
    
    init(nickname: String, age: Int){
        self.nickname = nickname
        self.age = age
    }
    
    // 생성자 오버로딩
    init(age: Int){
        self.nickname = "BSJ"
        self.age = age
    }
    
    // 소멸자. 클래스에서만 선언 가능
    deinit {
        print("deinit User")
    }
    
}

var user = User(nickname: "KSW", age: 26)
user.nickname
user.age

var user2 = User(age: 27)
user2.nickname
user2.age

var user3: User? = User(age: 29)
// nil을 대입시키면 인스턴스가 더 이상 필요하지 않다고 판단.
// 소멸자 호출
user3 = nil

프로퍼티

  1. 저장 프로퍼티 : 인스턴스의 변수 또는 상수
  2. 연산 프로퍼티 : 특정 연산을 실행한 결과값
  3. 타입 프로퍼티 : 특정 인스턴스가 아닌 특정 타입에서 사용됨
  • 프로퍼티 옵저버 willSet, didSet

Swift 코드

// 저장 프로퍼티
struct Cat {
    var name: String
    let gender: String
}

var cat = Cat(name: "Cloud", gender: "male")
print(cat)
cat.name = "Binu"
cat.name

// 구조체와 클래스의 차이점
let cat2 = Cat(name: "Momo", gender: "male")
// cat2.name = "Cloud" -> let 상수로 선언 했기 때문에 오류 !

// 하지만 클래스는 let으로 선언해도 프로퍼티 값 변경이 가능하다.
class Rabbit{
    var name: String
    let gender: String
    
    init(name: String, gender: String){
        self.name = name
        self.gender = gender
    }
}
    
let rabbit = Rabbit(name: "Cookie", gender: "male")
rabbit.name = "Cloud"
rabbit.name

// 구조체는 value 타입이기 때문에, 상수로 선언하면 프로퍼티 변경이 되지 않음.
// 클래스는 참조 타입이기 때문에, 상수로 선언해도 프로퍼티 변경이 가능하다.

// 계산(연산) 프로퍼티
// 저장 프로퍼티는 구조체, 클래스에서만 사용이 가능했다.
// 계산 프로퍼티는 열거형까지 사용이 가능하다.
// 계산 프로퍼티는 getter와 setter를 사용한다.
// get만 구현하면 읽기 전용 프로퍼티가 된다.
// set의 매개변수 이름을 설정하지 않으면 default로 "newValue"라는 이름으로 사용 가능하다.
struct Stock {
    var averagePrice: Int
    var quantity: Int
    // 계산 프로퍼티
    var purchasePrice: Int {
        get {
            return averagePrice * quantity
        }
        set(newPrice) {
            averagePrice = newPrice / quantity
        }
    }
}

var stock = Stock(averagePrice: 2300, quantity: 3)
print(stock)
stock.purchasePrice
stock.purchasePrice = 3000
stock.purchasePrice
stock.averagePrice

// 프로퍼티 옵저버
// 프로퍼티 값 변화를 관찰하고 반영한다.
// 새로운 값이 기존값과 같더라도 호출된다.
// 프로퍼티 값이 set 될 때마다 호출된다고 생각하면 된다.

// 3가지 경우에 사용가능
// 저장 프로퍼티, 오버라이딩 된 저장, 계산 프로퍼티

// willSet : 값이 저장되기 직전
// didSet : 값이 저장된 직후

class Account {
    var credit: Int = 0{
        willSet {
            print("잔액이 \(credit)원에서 \(newValue)원으로 변경될 것입니다.")
        }
        didSet {
            print("잔액이 \(oldValue)원에서 \(credit)원으로 변경 되었습니다.")
        }
    }
}

var account = Account()
account.credit = 1000

// 타입 프로퍼티
// 인스턴스의 생성 없이 객체 내의 프로퍼티에 접근 가능하게 하는 것
// 프로퍼티의 타입 자체와 연결하는 것
// 타입 프로퍼티는 저장 프로퍼티와 연산 프로퍼티에서만 사용 가능하다.
// static 키워드를 사용하다.
struct SomeStructure {
    static var storedTypeProperty = "Some value"
    
    static var computedTypeProperty: Int {
        return 100
    }
}

SomeStructure.storedTypeProperty = "Hello"
SomeStructure.computedTypeProperty
SomeStructure.storedTypeProperty

구조체 vs 클래스

공통점

  1. 값을 저장할 프로퍼티를 선언할 수 있음

  2. 함수적 기능을 하는 메서드를 선언할 수 있음

  3. 내부값에 .을 사용하여 접근할 수 있음

  4. 생성자를 사용해서 초기 설정을 할 수 있음

  5. extension을 사용하여 기능 확장을 할 수 있음

  6. Protocol을 채택하여 기능을 설정 할 수 있음

차이점

  • 클래스
    • 참조 타입 (Reference Type)
    • 힙에 메모리 저장
    • ARC로 메모리를 관리
    • 상속이 가능
    • 타입 캐스팅을 통해 런타임에서 클래스 인스턴스의 타입을 확인
    • deinit 소멸자를 사용할 수 있음
    • 같은 클래스 인스턴스를 여러 변수에 할당한 뒤 값을 변경 시키면 모든 변수에 영향을 줌 (메모리가 복사됨)
  • 구조체
    • 값 타입 (Value Type)
    • 스택에 메모리 저장
    • 구조체 변수를 새로운 변수에 할당할 때마다 새로운 구조체가 할당 됨
    • 즉 같은 구조체를 여러 변수에 할당한 뒤 값을 변경 시키더라도 다른 변수에 영향을 주지 않음 (값 자체를 복사)

profile
안녕하세요, iOS 와 알고리즘에 대한 글을 씁니다.
post-custom-banner

0개의 댓글