본문 바로가기

카테고리 없음

[Swift] 클래스를 파헤쳐 봅시다!

struct 와 class 코드를 동시에 작상하고 struct먼저 알아봅니다.

struct BodyStructure{

    var head = 1
    var arm = 2
    var body = 0
    var leg = 0

}



class InsideBody{

    var bodyStructure = BodyStructure()
    var brain: Int = 0
    var blood: String = ""
    var bone: Bool = true
    var muscle: String = ""
    var long_term: Int = 0 //장기

}

속성과 클래스를 작성할때는 CamelCase로 작성한다.

정의한 struct와 class에서는 속성에대해서 설명하지않고 구조만잡는다. 고로

속성에대해서 설명이 필요할때는 struct와 class에 대한 인스턴스를 만들어야한다.

 

struct 와 class인스턴스에 대해 이니셜라이저 구문을 사용한다.

Ex) 

let someBodyStructure = BodyStructure()
let someInsideBody = InsideBody()

 

여기서잠깐!

이니셜라이저란 ?

initializer(초기화)= 재정의 해서사용하는 것

즉, 새로운 변수에 담아서 그안 변수들을 사용하는 것 이다

 

이니셜라이저의 가장 간단한 형식은 class 또는 struct 유형 이름 뒤에 BodyStructure()와 같은 빈괄호를 사용하는 것

한번더 노출

let someBodyStructure = BodyStructure()
let someInsideBody = InsideBody()

 

이렇게 사용하면 모든 속성이 기본값으로 초기화된 class 또는 struct의 새 인스턴스가 생성됩니다.

 

 

그리고 이를 타입추론을 이용하여 접근할 수 있습니다.

.

 

print("\n\n\n\n")
print("내 몸구조인 팔의 개수는 \(someBodyStructure.arm)")

이 안에서 arm의 값을 반환하여 "내 몸구조인 팔의 개수는 2"를 출력한다.

 

그리고 여기서 더 재미있는건

print("내 몸구조인 팔의 개수는 \(someInsideBody.bodyStructure.arm)")

 

이 안에서 arm의 값을 반환하여 "내 몸구조인 팔의 개수는 2"를 출력한다.

이와같이 타입추론을 이용해서( . ) 하위속성으로 가져올 수 도 있다. /  . 로 사용 할 수 있으며

someInsideBody.bodyStructure.arm = 10

 

추가로 새 값고 할당이 가능하다

print("내 몸구조인 팔의 개수는 \(someInsideBody.bodyStructure.arm)")

"내 몸구조인 팔의 개수는 10"를 출력한다.

 

흠 ..만약에 10개라면... 코딩하는 효율이 얼마나 좋을까 ㅎ

 

let sbs = BodyStructure(head: 3, arm: 6, body: 3, leg: 4)

이렇듯 모든 구조에는 새 구조 인스턴스를 생성하는데 사용할 수 있는 자동생성되는 이니셜라이저가 존재합니다.

새 인스턴스의 대한 초기값은 이름으로 멤버별 이니셜라이저를 전달 할 수 있습니다!

 

빨간색글씨로, 단, 구조체와달리 클래스는 기본 멤버별 이니셜라이저를 받지 않습니다

자세한 내용은 이곳을 참조해주세요 - https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

 


"" 값 유형은 변수 또는 상수에 할당되거나 함수에 전달될 때 값이 복사되는 유형입니다.

여러분은 실제로 이전 장에서 가치 유형을 광범위하게 사용해 왔습니다. 사실, Swift의 모든 기본 유형(정수, 부동 소수점 번호, Booleans, 문자열, 배열 및 사전)은 가치 유형이며 배후의 구조로 구현됩니다.

모든 구조와 열거형은 Swift의 값 유형입니다. 즉, 사용자가 생성한 구조 및 열거 인스턴스 및 해당 인스턴스 및 해당 인스턴스들이 속성으로 가지고 있는 값 유형은 코드에 전달될 때 항상 복사됩니다. ""


//하 뭔소리냐 이게 그니깐 생성한 모든 구조 및 열거형 인스턴스와 속성으로 포함된 모든 값 유형은 복사가 된다 이게 포인트인가?

 

let bd = BodyStructure(head: 1, arm: 2, body: 1, leg: 2)
var dog = bd

그러니깐 현재 이상태를 설명하자 코드로 설명하자면,,,

 

dog라는 새 변수에 bd.BodyStructure()라는 기존 인스턴스 값이 복사가 되

새 값이 할당이된거다. 복사(bd.BodyStructture())값이 -> dog로 복사됨

 

dog.head = 1
dog.arm = 0
dog.body = 1
dog.leg = 4

//서로 값은 현재 같지만 서로 완전히 다른 인스턴스의 값이다 ?????? 뭔 dog 같은 소리냐하면

 

print("내 몸구조인 팔의 개수는\(dog.arm)")
//"내 몸구조인 팔의 개수는0"
print("---------")
print("내 몸구조인 팔의 개수는\(bd.arm)")
//"내 몸구조인 팔의 개수는2"

 

별도의 인스턴스이기 때문에 아래와 같이 팔 개수를 dog를 0설정해도 에 저장된 팔에는 영향을 미치지 않습니다 bd.

 

아래 비포 에프터는 메모리 올라갔을 때를 표현

 

//                                         Before                                       |                                              After

//                                                                                           |             bd -> (head: 1, arm: 2, body: 1, leg: 2)

//              bd -> (head: 1, arm: 2, body: 1, leg: 2)            |           dog -> (head: 1, arm: 0, body: 1, leg: 4)

//                                                                                           |

//                                                                                           |

 

열거형도 마찬가지라는데 아직 열거형에대해서는 공부가 안되있어 이전단계이긴하지만 바로 다음 공부하는게 나을듯하다..... 기다려라;;; 금방

열거형을 접수한다 .... 후,,,,

 

 

 


 

하지만 ,,

클래스는 참조형 유형이다 ?!?!

 

"""
 작성할때 참고용
class InsideBody{
    var bodyStructure = BodyStructure()
    var brain: Int = 0
    var blood: String = ""
    var bone: Bool = true
    var muscle: String = ""
    var long_term: Int = 0 //장기
}
"""

let cat = InsideBody()
cat.bodyStructure = bd
cat.brain = 1
cat.blood = "빨간색"
cat.bone = true
cat.muscle = "뒷다리가 강화돼있음"
cat.long_term = 78

 

이번에는 새 상수인 cat을 InsideBody()의 새 인스턴스를 참조하도록 설정

고양이 몸은 아까 dog = bd로 복사설정했던 값으로 할당, 뇌는 1, 피는 빨간색 으로할당, 뼈는 존재 로할당, 근육은 뒷다리가 강화돼있음 로 할당, 장기개수는 사람과 같이 78로 할당

 

let alsoCat = cat
alsoCat.long_term = 88

 

클래스는 참조유형이기때문에 실제로 alsoCat과 cat 모두 동일한 InsideBody()인스턴스를 참조한다.

사실상 아래와 같은 그림과 같이 동일한 단일 인스턴스에 대해 두개의 다른 이름일 뿐이다.

 

아래 비포 에프터는 메모리 올라갔을 때를 표현

 

//                          Before                                        |                                         After

//                                                                             |

//    cat ->    bodyStructure = bd                          |        (cat, alsoCat)->        bodyStructure = bd

//                   brain = 1                                            |                                           brain = 1

//                   blood = "빨간색"                               |                                           blood = "빨간색"

//                   bone = true                                      |                                           bone = true

//                   muscle = "뒷다리가 강화돼있음"       |                                           muscle = "뒷다리가 강화돼있음"

//                   long_term = 78                                |                                           long_term = 88

//                                                                             |

 

print("내 몸의 장기의 개수는\(alsoCat.long_term)")
//"내 몸의 장기의 개수는88"
print("---------")
print("내 몸의 장기의 개수는\(cat.long_term)")
//"내 몸의 장기의 개수는88"

 

//엇??!?!? struct(구조)와 달리 class는 값변경 이전의 값을 호출해도 그대로 안 가져오네 ??

 

전기로 따지면 stuct(구조)는 전기가 인스턴스 변경 전후로 연결이안되는 '도체(전기가안통하는)'지만

class는 변경 전 후가 통일되는 '절연체(전기가통하는)'네?

이런 비유가 적절한지모르겠지만 뭔가 이렇게 떠올리니 확 정리가 된느낌이군,,

 

그니깐 방금 선언된 let alsoCat과 let cat은 둘다 상수이기때문에 alsoCat.long_term = 88값은 let cat을 변형한것이아니라

맨처음 기본값인 class InsideBody값을 번형시켰다는 의미인가 ??

 

 

ID 연산자

클래스는 참조 유형이기 때문에 여러 상수와 변수가 뒤에서 클래스의 동일한 단일 인스턴스를 참조할 수 있습니다. (구조 및 열거형의 경우에는 동일하지 않습니다. 상수 또는 변수에 할당되거나 함수에 전달될 때 항상 복사되기 때문입니다.)

 

두 개의 상수 또는 변수가 클래스의 정확히 동일한 인스턴스를 참조하는지 여부를 찾는 것이 때때로 유용할 수 있습니다. 이를 활성화하기 위해 Swift는 두 가지 ID 연산자를 제공합니다.

 

//( ===)와 동일

//( !==)와 동일하지 않음

다음 연산자를 사용하여 두 개의 상수 또는 변수가 동일한 단일 인스턴스를 참조하는지 확인할 수 있따

 

if cat === alsoCat {
    print("cat and alsoCat refer to the same InsideBody instance.")
}

// struct는 참조를 하지않기때문에 확인하는 ID는 없다는 것이다.
// Prints "cat 및 alsoCat은 동일한 InsideBody 인스턴스를 참조합니다."

 


오늘의 결론

  • struct(구조)는 각각 '도체'의 특성을 가지고 있으며 A인스턴스 값을 B로 변경했을시 struct(원본) <- A인스턴스 <- B인스턴스 이런 식으로 개별 구조로 값을 복사하는 것이기 때문에 메모리에 올라갈때 위 그림과같이 서로다른 인스턴스로 저장이되지만

 

  • class(클래스)는 '절연체'의 특성을 가지고 있어 A인스턴스 값을 B로 변경했을 시 class(클래스) = A인스턴스 = B인스턴스 값은 참조하는 것이기 때문에 서로 같은 인스턴스로 저장이된다.

 

 

더 쉽게 말해서

class는 마지막 변경된 값으로 동일하게 메모리에 올라가지만

struct는 각각 다른 값으로 메모리에 올라간다.

 

 

 

참조링크

 

https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html