본문 바로가기
IOS/Swift

[Swift] 구조체와 클래스(Structures and Classes)

by 얘리밍 2023. 2. 8.
320x100
728x90

 

📌 구조체와 클래스 차이

  구조체 클래스
공통점 1. 저장할 수 있다.

2. 메소드를 정의할 수 있다.

3. 서브 스크립트 정의를 통해 값에 접근 가능

4. 초기화 상태 정의 가능

5. 기능적 확장 가능 

6. 표준 프로토콜 준수 
차이점 1. 타입을 추론하기 쉬움

2. struct 키워드로 시작 

3. 값 타입(value Types) 임 
1. class 키워드로 시작 

2. 상속 사용 가능(한 클래스가 다른 클래스의 특성 상속 가능)

3. 타입 캐스팅을 사용하면 런타임 시에 클래스 인스턴스 확인 가능

4. 초기화 해제 구문 -> 클래스 인스턴스가 할당된 리소스 해제 가능

5. 자동 참조 카운팅을 통해 하나 이상의 인스턴스 참조를 허락함  

6. 참조 타입(Reference Types) 임

단점 ) 복잡성 증가 

 

 

 

 

구조체와 클래스 생성 정의 

 

1. 구조체와 클래스의 이름UpperCameCase를 사용한다(첫 시작 대문자)

2. 프로퍼티lowerCameCase를 따른다. (소문자 시작) 

struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

 

 


 

1️⃣ 인스턴스 생성

 

let someResolution = Resolution()
let someVideoMode = VideoMode()

 


 

2️⃣ 프로퍼티 접근

 

Resolution의 width 프로퍼티에 접근하고 싶다면, 

인스턴스 뒤에 구분자(.)를 통해 접근하면 된다. 

print("너비는 \(someResolution.width)")
// Prints 너비는  0

 

VideoMode는 Resolution 구조체를 프로퍼티로 가지고 있다

VideoMode에서 Resolution 구조체의 width 서브 프로퍼티에 접근하려면 연쇄 접근하면 된다.

someVideoMode 인스턴스 -> resolution 프로퍼티 -> width 서브 프로퍼티 

print("someVideoMode의 너비 \(someVideoMode.resolution.width)")
// Prints someVideoMode의 너비 0

 

 


 

3️⃣ 구조체 멤버 초기화

 

구조체는 멤버별 초기화 구문을 다음과 같이 갖고 있지만, 클래스 인스턴스는 멤버별 초기화를 받지 않는다

let vga = Resolution(width: 640, height: 480)

 


 

4️⃣ 구조체의 값 복사 

 

hd 상수를 선언하여 Resolution 인스턴스를 초기화하여 설정한다음, 

cinema라는 변수에 hd 값을 할당한다. 

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

 

 

hd와 cinema는 현재는 같은 값을 가지지만, 둘은 완벽히 다른 인스턴스 이다. 

 

cinema의 width를 변경해보자.

cinema의 width가 2048으로 변경되어 출력될 것이다. 

cinema.width = 2048

print("cinema is now \(cinema.width) pixels wide")
 // cinema is now 2048 pixels wide

 

 

하지만 기존의 hd의 width는 변경되지 않고 1920 기존 값을 유지한다. 

다음과 같이 둘은 완벽히 다른 인스턴스이다. 

 

 

 

 

 

 

열거형에서도 같이 동작된다. 

다음과 같은 열거형이 있으며 current와 remembered 변수 상수를 통해 값 할당과 복사를 했다고 하자.

// 열거형 선언 
enum CompassPoint {
    case north, south, east, west
    mutating func turnNorth() {
        self = .north
    }
}

var current = CompassPoint.west    //프로퍼티 할당
let remembered = currentDirection  // current 복사

 

 

이 후, current만 CompassPoint의 turnNorth 함수를 호출해본다. 

current.turnNorth()

 

 

아마 값이 north로 변경 되었을 것이다.

그렇다면 remembered는? 

 

 

 

 

이제 current의 값과 remembered의 값을 확인해보자.

print("current의 방향은 \(currentDirection)")
print("remembered의 방향은 \(rememberedDirection)")
// Prints current의 방향은north
// Prints remembered의 방향은 west

remembered는 current의 복사본으로 current의 값이 변경되어도 복사본에는 영향을 주지 않기 때문에

기존 할당값인 west로 유지된다. 

 

 

 

이를 통해 구조체열거형값 타입임을 알 수 있다. 

값 타입 (value type) 은 변수 또는 상수에 할당될 때나 함수에 전달될 때 복사 되는 값인 타입

 

 

 


 

 

 

 

 

🤔 그렇다면 클래스는?

 

 

클래스참조 타입(Reference Types)

참조 타입 (reference types) 은 변수 또는 상수에 할당될 때나 함수로 전달될 때 복사되지 않음

 

 

 

위 VideMode 클래스를 다시 살펴보자 

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

 

 

그리고 tenEighty 상수에 VideoMode 인스턴스를 할당하고 그 프로퍼티 속성 값을 다음과 같이 설정한다.

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

 

 

 

그리고 또 다른 상수 alsoTenEighty에 tenEighty를 할당해보자

그리고 나서 alsoTenEighty의 frameRate 값을 30.0으로 바꾸면 tenEighty의 frameRate 프로퍼티는 어떻게 될까??

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

 

 

 

🔎 결과)

print("tenEighty의 frameRate은 \(tenEighty.frameRate)")
// Prints tenEighty의 frameRate은 30.0

tenEighty.frameRate의 값 또한 30.0으로 변경된 것을 볼 수 있다. 

 

 

 

왜😮??

tenEighty와 alsoTenEighty는 같은 VideoMode 인스턴스를 참조하기 때문이다. 

 

 

 

클래스는 구조체와 열거형과는 다르게 값 저장이 아닌, 값 참조이기 때문 

 

 


 

 

5️⃣ 식별 연산자

 

  • 동일 인스턴스 (Identical to) (===)
  • 동일하지 않은 인스턴스 (Not identical to) (!==)
  •  
    동일 인스턴스는(3개의 등호로 표시, ===)  같음(equal to, 2개 등호, ==)과 같다는 말은 아니다. 
     
     
동일 인스턴스 (3개의 등호로 표시, ===)  래스 타입의 상수 또는 변수가 동일한 클래스 인스턴스를 참조함
같음(2개 등호, ==)  두 인스턴스 값이 동일하거나 동등함 

 

 

 

 

 

728x90
반응형