Notice
Recent Posts
Recent Comments
Link
大器晩成
클래스와 구조체의 차이 본문
*구조체와 클래스의 가장 큰 차이는 메모리 저장 방식의 차이입니다.*
| 구조체 | 클래스 |
|
|
클래스의 메모리
class Person {
var name = "태연"
}
var p = Person() // 가상의주소: 0x9001
p.name // "태연"
var p2 = p // (클래스) // 가상의주소: 0x9001
p.name = "카리나"
print(p2.name) //"카리나"
p2.name = "윈터"
print(p.name) //"윈터"
- 클래스는 참조타입으로 복사 시 저장된 주소를 전달합니다.
- 즉, "var p2 = p" 코드는 p가 가리키는 주소값을 복사해서 p2에 전달하는 것입니다.
- 참조란 객체가 저장된 메모리 주소 정보가 전달된다는 뜻입니다.
- p에서 값이 변경되면, 주소값을 동일한 주소값을 가리키는 p2도 값이 변경됩니다.
- 실제로는 힙에 있는 값이 변경되는 것입니다. (스택에서는 힙의 인스턴스를 가리키고 있습니다.) - 즉, p와 p2는 같은 객체입니다.
구조체의 메모리
struct Person {
var name = "태연"
}
var p = Person()
p.name // "태연"
var p2 = p // (구조체)
p.name = "카리나"
print(p2.name) //"태연"
p2.name = "윈터"
print(p.name) //"카리나"
- 구조체는 값 타입으로 현재의 데이터를 복사합니다.. 만약 p.name의 이름을 변경하고 복사를 하면 변경된 값이 복사됩니다.
- 변수에 대입된 인스턴스와 기존의 인스턴스는 서로 독립적입니다. (즉, a와 a2는 서로 다른 인스턴스이다.
클래스의 let과 var 키워드
- var와 let을 사용하여 객체를 생성할 때의 차이는 객체 자체를 수정할 수 있는지 여부에 달려 있습니다.
[let]
class Person {
var name: String
init(name: String) {
self.name = name
}
}
let person = Person(name: "John")
// Error: Cannot assign to value: 'person' is a 'let' constant
// person = Person(name: "Alice") // 다른 객체로 변경할 수 없다.
person.name = "Alice" // 객체 내부의 속성은 변경 가능
print(person.name) // Alice
--------------------------------------------------------
[var]
var person2 = Person(name: "John")
person2.name // "John"
person2 = Person(name: "Alice") // 객체 자체를 변경할 수 있음
person2.name // "Alice"
person2.name = "Bob" // 객체의 속성도 변경 가능
person2.name "Bob" // Bob
--------------------------------------------------------
class PersonClass {
var name = "사람"
var age = 0
}
let pclass = PersonClass()
pclass.name = "사람1"
pclass.name
PersonClass().name // 왜 "사람1"이 나오지 않을까요?
//pclass와 PersonClass().name는 완전히 다른 인스턴스이다.
* 클래스는 객체의 틀이며, 같은 클래스 타입으로 생성된 인스턴스여도 서로 독립적인 관계이다.
let을 사용할 때:
- 불변 객체: let으로 선언한 객체는 변수 자체는 변경할 수 없지만, 객체 내부의 속성이나 메서드는 수정이 가능할 수 있습니다.
- 중요한 점은, 객체 자체를 다른 객체로 변경할 수 없다는 것입니다. 즉, let을 사용하여 객체를 생성한 후, 해당 객체를 다른 객체로 대체할 수 없다.
var를 사용할 때:
- 가변 객체: var로 선언한 객체는 객체 자체와 객체의 속성을 모두 변경할 수 있습니다.
- 객체를 새로운 객체로 바꾸거나, 객체의 속성을 수정하는 것이 가능합니다.
| let | var |
|
|
구조체의 let과 var 키워드
- 스위프트에서 구조체를 사용할 때 let과 var의 차이는 클래스와 비슷하지만, 값 타입인 구조체는 참조타입인 클래스와 다르게 동작합니다. 구조체는 값을 복사하는 특성이 있기 때문입니다.
#1. 예시1
struct AnimalStruct {
var name = "동물"
var age = 0
}
let astruct = AnimalStruct()
//astruct.name = "동물1" // let으로 선언해서 수정 불가능
astruct.name // "동물"
#2. 예시2
struct Person {
var name: String
let age: Int
}
let person = Person(name: "John", age: 30)
// person = Person(name: "Alice", age: 25) // Error: Cannot assign to value: 'person' is a 'let' constant
//person.name = "Alice" // Error: Cannot assign to property: 'person' is a 'let' constant
// person.age = 31 // Error: Cannot assign to property: 'age' is a 'let' constant
var person = Person(name: "John", age: 30)
person = Person(name: "Alice", age: 25) // 구조체 자체를 다른 값으로 변경 가능
person.name = "Bob" // name 속성 변경 가능
// person.age = 31 // age는 구조체에서 let으로 선언되었기 때문에 변경 불가
let으로 선언한 구조체 인스턴스
- let으로 선언된 구조체 인스턴스는 구조체 자체와 속성 모두 수정할 수 없습니다.
- 구조체 내부에 var로 선언된 속성이라도, 구조체 자체가 불변이기 때문에 해당 속성을 변경하려고 하면 에러가 발생합니다.
var로 선언한 구조체 인스턴스
- var로 선언된 구조체 인스턴스는 구조체 자체와 속성 모두 수정할 수 있습니다.
- 구조체 내의 var로 선언된 속성도 변경할 수 있습니다.
| let | var |
|
|
접문법/ 명시적 멤버 표현식(Explicit Member Expression)의 정확한 의미
// 내부의 요소. 즉, 클래스, 구조체의 인스턴스의 멤버에 접근한다.
// 멤버는 속성, 메서드를 포함
struct Bird {
var name = "새"
var weight = 0.0
func fly() {
print("날아갑니다.")
}
}
var bBird = Bird()
bBird.fly()
Int.random(in: 1...10)
- 점문법은 하위의 프로퍼티(속성) 또는 메서드(함수)를 가리킵니다.
- 프로퍼티의 하위 프로퍼티에 값을 할당 또는 접근할 때도 점문법을 연속으로 연결하여 값을 할당 또는 접근할 수 있다.
관습적인 부분들에 대한 이해
- 일반적으로 클래스, 구조체 선언할때 모두
- 1) 속성 2) 메서드 순서대로 작성
- 클래스 내부에는 직접 메서드(함수) 실행문이 올 수 없다.
- 메서드 실행문은 메서드 정의문 내에 존재해야 함.
// 속성, 메서드 순서대로 작성
struct Bird {
var name = "새"
var weight = 0.0
func fly() {
run() // 메서드 실행문은 메서드 정의문 내에 존재
print("날아갑니다.")
}
func run() {
print("달려갑니다.")
}
//run() // 에러 발생
}
var bBird = Bird()
bBird.fly() // 출력: 달려갑니다. 날아갑니다.
식별연산자(Identity Operators)
// 식별연산자 - 두개의 참조가 같은 인스턴스를 가리키고 있는지를 비교하는 방법
// 동일 인스턴스인지 비교할 때: ===
// 동일 인스턴스가 아닌지 비교할 때 : !==
class Person {
var name = "카리나"
let age = 25
}
var person = Person()
var person2 = Person()
if (person === person2) {
print("동일한 인스턴스를 참조하고 있다.")
} else {
print("서로 다른 인스턴스를 참조하고 있다..")
}
// 출력: 서로 다른 인스턴스를 참조하고 있다..
var person3 = person
if (person === person3) {
print("동일한 인스턴스를 참조하고 있다.")
} else {
print("서로 다른 인스턴스를 참조하고 있다..")
}
// 출력: 동일한 인스턴스를 참조하고 있다.
- **식별 연산자 (===, !==)**는 클래스 타입의 객체에만 사용 가능합니다.
- 구조체나 열거형은 값 타입이므로, 식별 연산자를 사용할 수 없습니다.
- 값 타입에서는 == 연산자를 사용하여 값이 같은지 비교할 수 있습니다.
728x90
'iOS > Swift 문법' 카테고리의 다른 글
| 저장속성(Stored Properties) (0) | 2024.11.21 |
|---|---|
| 초기화(initializer) (0) | 2024.11.21 |
| 구조체(Struct)와 클래스(Class) (1) | 2024.11.21 |
| 옵셔널 체이닝 (4) | 2024.11.12 |
| inout 파라미터 (0) | 2024.11.08 |