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