class VideoMode {
var interlaced = false
var frameRate = 0.0
var name: String?
func desc() -> String {
return "VideoMode 클래스"
}
}
name은 초기값 할당되지 않음 + 옵셔널 타입 프로퍼티
이런 경우에는 nil 값으로 초기화된다 (값이 존재하지 않음)
Instance
클래스로부터 만들어진 객체
실제로 메모리에 할당되어서 동작할 수 있는 모양을 갖춘 것
// Resolution 구조체에 대한 인스턴스를 생성하고 상수 insRes에 할당
let insRes = Resolution()
// VideoMode 클래스에 대한 인스턴스를 생성하고 상수 insVMode에 할당
let insVMode = VideoMode()
구조체/클래스 뒤에 오는 소괄호는 인스턴스 생성 연산자
. 점 구문(Dot Syntax)를 이용해서 인스턴스 하위 객체(혹은 프로퍼티의 값)에 접근 / 할당 할 수 있다
<인스턴스 이름>.<프로퍼티 이름>
// 연속해서 사용할 수 있다
vMode.res.width
점 구문을 연속으로 연결해서 사용할 수 있다
이것을 체인 Chain 방식이라고 한다
Initialize
명시적인 초기화
프로퍼티를 선언하는 동시에 초기값 지정
초기화 메서드 안에서 프로퍼티의 초기값 지정
⭐ 모든 프로퍼티는 인스턴스가 생성되는 시점까지는 반드시 초기화되어야 한다 ⭐
명시적인 초기화의 경우가 아니라면, 옵셔널 타입으로 선언해서 자동으로 nil을 할당받게 만들어주어야 한다
- 구조체 Initialize
멤버와이즈 초기화 구문 Memberwise Initialiser
모든 프로퍼티의 값을 인자값으로 입력받아 초기화하는 기본 초기화 구문
인스턴스를 생성하는 형식 정의
입력된 인자값을 이용해서 프로퍼티를 초기화
// width와 height를 매개변수로 하여 Resolution 인스턴스를 생성
let defaultRes = Resolution(width: 1024, height: 768)
print("width : \(defaultRes.width), height : \(defaultRes.height)")
// 실행 결과
width : 1024, height : 768
빈 괄호 초기화 구문
아무런 인자값을 입력받지 않음
어떤 프로퍼티도 초기화하지 않음
단순히 구조체의 인스턴스를 생성하기만 한다
사용하려면, 모든 프로퍼티는 선언과 동시에 초기화가 되어 있어야 한다
- 클래스 Initialize
빈 괄호 초기화 구문 사용
클래스의 초기화 원칙
모든 프로퍼티는 정의할 때 초기화를 한다 OR 옵셔널 타입으로 선언한다
인스턴스를 생성할 때는 클래스 명 뒤에 소괄호() - 인스턴스 생성 연산자 - 를 붙여준다
구조체의 값 전달 Value Type
복사에 의한 전달
생성하는 모든 구조체 인스턴스들이 상수나 변수에 할당될 때 / 함수의 인자값으로 사용될 때 복사해서 사용된다
정수, 문자열, 배열 또는 딕셔너리 등 기본 자료형들은 모두 복사를 통해 값이 전달된다
해당 자료형이 구조체로 구현되었기 때문에
변수에 대입된 인스턴스와 기존의 인스턴스는 서로 독립적
구조체 인스턴스를 변수에 대입하면 기존의 인스턴스가 그대로 대입되는 것이 아니라 이를 복사한 새로운 값이 대입
서로에게 전혀 영향을 미치지 않는다
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
#1
print("cinema 인스턴스의 width 값은 \(cinema.width)입니다")
// 실행 결과
cinema 인스턴스의 width 값은 2048입니다
#2
print("hd 인스턴스의 width 값은 \(hd.width)입니다")
// 실행 결과
hd 인스턴스의 width 값은 1920입니다
클래스의 값 전달 Reference Type
참조에 의한 전달
참조❓
인스턴스가 저장된 메모리 주소 정보가 전달
항상 메모리 주소를 사용해 객체 자체를 전달
단순히 값을 넘긴다고 생각해도 된다
클래스는 참조 타입이기 때문에, 한 곳에서 수정할 경우 다른 곳에서도 적용된다
다양한 인자값에서 동시에 참조할 수 있어서, 메모리에 대한 이슈가 있다
- 클래스의 값 전달 Reference Type EX
let video = VideoMode()
video.name = "Original Video Instance"
print("video 인스턴스의 name 값은 \(video.name!)입니다.")
// video 인스턴스의 name 값은 Original Video Instance입니다.
let dvd = video
dvd.name = "DVD Video Instance"
print("video 인스턴스의 name 값은 \(video.name!)입니다")
// video 인스턴스의 name 값은 DVD Video Instance입니다
상수 video 는 클래스 VideoMode를 초기화하여 생성한 인스턴스이다
인스턴스 video의 name 값을 입력해주었고, 설정되었다
상수 dvd 는 인스턴스 video를 할당받았다
dvd의 속성값을 변경하였더니 video 의 속성값(프로퍼티)도 변경되었다
func changeName(v: VideoMode) {
v.name = "Function Video Instance"
}
changeName(v: video)
print("video 인스턴스의 name 값은 \(video.name!)입니다")
// video 인스턴스의 name 값은 Function Video Instance입니다
changeName 함수가 인자값으로 video 인스턴스를 전달받아서 프로퍼티 값을 변경하였다
if (video === dvd) {
print("video와 dvd는 동일한 VideoMode 인스턴스를 참조하고 있군요")
} else {
print("video와 dvd는 서로 다른 VideoMode 인스턴스를 참조하고 있군요")
}
// 실행 결과
video와 dvd는 동일한 VideoMode 인스턴스를 참조하고 있군요
video는 VideoMode 클래스의 인스턴스를 참조받았다
dvd는 video 인스턴스를 참조받았다
두 상수는 동일한 클래스 인스턴스를 참조한다
비교 연산 true
let vs = VideoMode()
let ds = VideoMode()
if (vs === ds) {
print("vs와 ds는 동일한 VideoMode 인스턴스를 참조하고 있습니다")
} else {
print("vs와 ds는 서로 다른 VideoMode 인스턴스를 참조하고 있습니다")
}
// 실행 결과
vs와 ds는 서로 다른 VideoMode 인스턴스를 참조하고 있습니다
vs 인스턴스와 ds 인스턴스는 각각 VideoMode 클래스의 인스턴스를 새롭게 생성하여 참조받았다
동일한 타입의 인스턴스이지만, 같은 메모리 주소를 참조하는 것은 아니다
비교 연산 false
구조체를 사용하는 경우
서로 연관된 몇 개의 기본 데이터 타입들을 캡슐화하여 묶는 것이 목적일 때
캡슐화된 데이터에 상속이 필요하지 않을 때
캡슐화된 데이터를 전달하거나 할당하는 과정에서 참조 방식보다는 값이 복사되는 것이 합리적일 때