본문 바로가기
모바일앱/Swift

클래스, 언제 클래스? 언제 스트럭트?

by GeekCode 2021. 10. 16.
반응형

클래스 개념

 

클래스는 스트럭쳐 처럼 관계가 있는 것들을 묶어서 표현한다.

 

Object = Data + Method
Objects는 클래스와 스트럭쳐 형태로 만들 수 있다.

하지만 두가지의 차이점은 실제 동작에서 차이가 있다. 

 

 

Reference Type
Value Type

생성되는 인스턴스가 할당되는 메모리의 차이가 있다. 

Structure는 Stack이라는 공간에 생성된다.

Class는 Heap이라는 공간에 생성된다.

 

Stack Heap은 다른 속성을 갖고 있는 메모리 공간이다. 

Stack

시스템에서 당장 실행해야하거나 타이트하게 컨트롤 및 매니징 해야하는 경우

함수를 생성 , 처리후 리턴하고 해당 변수도 스택에서 제거가 되나. 효율적이고 빠르다.

 

Heap

시스템에서 클래스 같은 레퍼런스타입을 저장하는 데 사용된다. 큰 메모리 풀을 가지고 있어서 시스템에서 동적으로 메모리 할당요청할 수 있다. 하지만 Heap은 스택처럼 자동으로 데이터를 제거하지않아서 개발자가 신경을 써줘야한다. 그래서 개발자가 신경을 쓰지않아도 되도록 Xcode같은데서 도와준다.  스택보다는 느리다.

 

변수 자체는 스택 공간에 생성된다. 이 레퍼런스에는 클래스 인스턴스의 주소를 가지고 있다. 

생성된 클래스 인스턴스는 Heap공간에 있다.

 

다시 정리

 

클래스 실습

import UIKit

struct PersonStruct {
    var firstName: String
    var lastName: String
    
    var fullName: String {
        return "\(firstName) \(lastName)"
    }
    mutating func uppercastName() {
//Cannot assign to property: 'self' is immutable
// -> mutating 앞에 붙이기
        firstName = firstName.uppercased()
        lastName = lastName.uppercased()
    }
}



class PersonClass {
    var firstName: String
    var lastName: String
    
//Class 'PersonClass' has no initializers -> 생성함수 넣어주세용
// -> init 생성하기 초기값 설정해주기
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
    
    var fullName: String {
        return "\(firstName) \(lastName)"
    }
    func uppercastName() { //mutating은 클래스에서 사용 안함
        firstName = firstName.uppercased()
        lastName = lastName.uppercased()
    }
}


var personStruct1 = PersonStruct(firstName: "Jason", lastName: "Lee")
var personStruct2 = personStruct1

var personClass1 = PersonClass(firstName: "Jason", lastName: "Lee")
var personClass2 = personClass1


//스트럭트는 기본적으로 각자의 할당값을 갖고있기 때문에 2을 Jay로 바꿔도 1은 변동없음
personStruct2.firstName = "Jay"
personStruct1.firstName //Jason
personStruct2.firstName //Jay

//클래스는 기본적으로 같은것을 가리키고 있기 때문에 2에 새로운 데이터를 할당하면  1에도 변화가 생긴다.
personClass2.firstName = "Jay"
personClass1.firstName //Jay
personClass2.firstName //Jay

//2가 새롭게 생성한 인스턴스를 가리킨다., 1은 변동없음
personClass2 = PersonClass(firstName: "Bob", lastName: "Lee")
personClass1.firstName //Jay
personClass2.firstName //Bob

//1에 2가 가리키는 것을 보라고 입력, 같은 내용을 가지게 된다.
personClass1 = personClass2
personClass1.firstName //Bob
personClass2.firstName //Bob

 

 

이럴때 Struct를 사용

 

언제 S

3가지

1. 두 object를 "같다,다르다"로 비교해야하는 경우

2. Copy된 각 객채들이 독립적인 상태를 가져야하는 경우

 

3. 코드에서 오브젝트의 데이터를 여러 스레드에 걸쳐 사용할 경우 

벨류 타입의 경우 해당 인스턴스가 카피된 유니크한 인스턴스를 가지고 있다.

한 객체에 여러 스레드가 동시에 접근했을때엔 잠재적인 위험이 있다. 밸류타입이라면 오히려 이 위험에 안전할 수 있다.

 

 

이럴때 Class를 사용

 

1. 두 object의 인스턴스 자체가 같음을 확인해야 할 때

진짜 객체자체가 같은지 확인

 

 

2. 하나의 객체가 필요하고, 여러 대상에 의해 접근되고 변경이 필요한 경우

앱개발을 할 때, ui application이라는 앱 개체가 있다. 유일한 하나의 개체인데 

앱내 여러 오브젝트에 의해 접근이 필요할 때가 있는데 이때는 래퍼런스 타입을 사용하면 된다.

 

 

 

 

 

 

 

단순하게

 

1. 일단 Struct로 쓰자

 나중에 클래스로 바꿀 필요를 느낄 때 하자

 

스위프트는 스트럭트를 선호하는 듯 하다. 

공식사이트에서 설명을 볼 수 있다.

https://developer.apple.com/swift/blog/?id=10/ 

 

Swift Blog - Apple Developer

Get the latest news and helpful tips on the Swift programming language from the engineers who created it.

developer.apple.com

 

2. 스택오버플로우 보다는 공식문서를 보자.

특히 웬만하면 공식문서에서 검색해보고 그다음 구글링을 해보자

공부해보고 내가 이해한 말로 다시 작성을 하는 습관을 가지자

 

 

 

 

반응형