[Swift 정면돌파] 07. 클래스 vs 구조체, 열거형

H43RO·2021년 8월 3일
1

Swift 정면돌파

목록 보기
7/19
post-thumbnail

본 시리즈는 아래 강의자료를 기반으로 작성되었습니다.
https://www.boostcourse.org/mo122/joinLectures/38564

오늘은 클래스와 구조체, 열거형 자료형의 가장 큰 차이점인 타입의 특성을 알아보았다. CS 지식과 연관이 있어 관련 내용도 함께 복습해보았고, 파이썬의 Call-by-assignment 라는 새로운 호출 방식을 알게 되었다.

Value Type (구조체, 열거형) vs Reference Type (클래스)

클래스는 참조 타입, 열거형과 구조체는 값 타입이라는 것이 가장 큰 차이
클래스는 상속이 가능하지만, 열거형과 구조체는 상속이 불가능

  1. Value Type : 데이터를 전달할 때 값을 복사하여 전달
  2. Reference Type : 데이터를 전달할 때 값의 메모리 위치 전달
struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()

// 두 번째 구조체 인스턴스에 첫 번째 인스턴스 값 복사
var secondStructInstance = firstStructInstance

// 두 번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없음
print("first struct instance property : \(firstStructInstance.property)")    // 1
print("second struct instance property : \(secondStructInstance.property)")  // 2

// 클래스 인스턴스 생성 후 첫 번째 참조 생성
let firstClassReference = ReferenceType()
// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조하기 때문에
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면
// 첫 번째 클래스 인스턴스의 프로퍼티 값을 변경하게 됨
print("first class reference property : \(firstClassReference.property)")    // 2
print("second class reference property : \(secondClassReference.property)")  // 2

값 타입을 사용하는 경우

→ 연관된 여러 값을 모아서 하나의 데이터 타입으로 표현하고 싶은 경우
→ 다른 객체, 함수 등으로 전달할 때 값 복사가 필요한 경우
→ 자신을 상속할 필요가 없거나, 상속받을 필요가 없는 경우

스위프트에서의 사용

→ 스위프트의 기본 데이터 타입은 모두 구조체로 구현 되어있음
→ 스위스트는 전반적으로 구조체와 열거형 사용을 선호함
→ Apple 프레임워크는 대부분 클래스를 사용함

관련 내용 다시 톺아보기

관련한 내용으로 기본 CS 지식인 'Call by value vs Call by reference' 에 대하여 다시금 복습해보았다!

Call-by-value

  • 함수가 호출될 때, 메모리 공간 안에서는 함수를 위한 별도의 임시 공간이 생성됨
    (c++의 경우 stack frame) 함수가 종료되면 해당 공간은 사라짐

  • 스택 프레임(Stack Frame) : 함수 호출시 할당되는 메모리 블록
    (지역변수의 선언으로 인해 할당되는 메모리 블록)

  • Call-by-value 값에 의한 호출방식은 함수 호출시 전달되는 변수의 값을 복사하여 함수의 인자로 전달
    복사된 인자는 함수 스코프 내에서 지역적으로 사용되는 local value의 특성을 가짐

  • 따라서 함수 안에서 인자의 값이 변경되어도, 외부의 변수의 값은 변경되지 않음

  • 보통 함수에 전달되는 인자의 데이터 타입 (원시자료형 / 참조자료형) 에 따라서 함수 호출 방식이 달라짐
    - 원시 자료형 (primitive type) : Call-by-value 로 동작 (Int, Short, Long, Float 등 )
    - 참조 자료형 (reference type): Call-by-reference 로 동작 (Array, Class Instance 등)

Call-by-reference

  • Call-by-reference 방식은 함수 호출시 인자로 전달되는 변수의 레퍼런스를 전달
    → 따라서 함수 안에서 인자의 값이 변경되면, 인자로 전달된 객체의 값도 함께 변경됨
#include <iostream>
using namespace std;

// 두 수를 함수 내에서 스왑
void callByValue(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}

// 두 수를 함수 내에서 스왑
void callByRef(int & a, int & b) {  // 포인터로도 구현 가능
	int temp = a;
	a = b;
	b = temp;
}

int main(void) {
	int a = 10;
	int b = 20;
	cout << "Before Swapping" << endl;
	cout << "a : " << a << endl;
	cout << " b : " << b << endl << endl << endl;

	callByValue(a, b);  // a, b 의 값은 그대로
	callByRef(a, b);    // a, b 의 값이 서로 바뀜

	cout << "After Swapping" << endl;
	cout << "a : " << a << endl;
	cout << " b : " << b << endl << endl << endl;

	return 0;
}

Call-by-assignment

  • 파이썬의 경우 함수의 호출 방식으로 Call-by-assignment을 사용
  • 파이썬에서는 모든 것이 객체이고, 객체는 총 2가지 종류가 있음
  1. Immutable Object (변하지 않는)
    - int, float, str, tuple 등
    - Immutable 객체가 인자로 전달되면 처음에는 Call by reference로 받지만, 값이 변경되면 Call by value로 동작
    - 즉 함수 내에서 Formal parameter 값이 바뀌어도, Actual parameter에는 영향이 없다.
  1. Mutable Object (변하는)
    - list, dict, set 등
    - Mutable 객체가 인자로 넘어가면 Call by reference로 동작한다.
    - 즉, Object Reference가 전달되어 Actual Parameter의 값에 영향을 미칠 수 있다.
def spam(eggs):  
   eggs.append(1) # Call by reference 로 동작 (Caller Scope 까지 적용)
   eggs = [2, 3] # Call by value 로 동작, 새로운 객체를 가르킴 (Caller Scope 영향 X)
   print(eggs)

ham = [0]  
spam(ham) # [2, 3]
print(ham) # [0, 1]
profile
어려울수록 기본에 미치고 열광하라

0개의 댓글