Rust Struct 알아보기

Struct는 rust 객체지향 프로그래밍의 기본인 되는 타입이자 자료구조입니다. 다른 언어에서 흔히 만날 수 있는 Class가 없기 때문에 객체지향의 패턴은 거의 Struct로 구현합니다.

그러니 기초부터 잘 이해하고 넘어가봅시다.

Struct 와 인스턴스

Strict는 기본적으로 튜플처럼 여러 타입의 데이터를 한데 묶는 데 사용합니다.

튜플과 다른 점은,

  1. 여러 인스턴스를 생성하는 템플릿 역할을 하고,
  2. 각 데이터에 이름을 부여할 수 있어, 인덱스 기반이 아니더라도 각 데이터를 가져올 수 있다는 점입니다.

새로운 Struct를 정의하는 방법은 다음과 같습니다.

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

우선, struct 키워드 뒤에 대문자로 시작하는 이름이 따라옵니다.,

struct의 각 데이터를 필드라고 하는데, 중괄호 {} 안에는 각 필드에 들어갈 이름과 타입을 명시합니다.

이렇게 정의한 Struct를 사용하려면 이 템플릿에 맞는 실제 데이터를 가진 인스턴스를 생성해주어야 합니다.

fn main() {
    let user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };
}

인스턴스를 정의할 때는 위와 같이 중괄호 {}와 실제 데이터를 입력합니다.

인스턴스인 user1의 데이터를 가져오거나, 수정할 때는 마침표 .를 활용하는 dot notation을 이용합니다.

    println!("{}", user1.email);

    user1.email = String::from("anotheremail@example.com");

rust의 Struct는 모든 필드가 수정가능하며, 특정 필드만 수정불가능하도록 지정할 수 없습니다.

또한, 기본값을 지정하는 등의 기능도 없기 때문에 함수를 이용해서 여러 가지 객체 생성 패턴을 구현합니다.

여러가지 패턴과 기능

필드 기본값 지정

다음은 기본값을 제공하는 패턴입니다.

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username: username,
        email: email,
        sign_in_count: 1,
    }
}

필드 active, sign_in_count에는 기본값을 두고, 그외의 필드에만 해당 데이터를 받아 User의 인스턴스를 생성합니다.

코드를 약간 줄여주는 field init shorthand

만약, 파라미터 이름과 필드 이름이 동일하다면 field init shorthand 기능으로 코드를 조금 덜 쓸 수도 있습니다

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
        sign_in_count: 1,
    }
}

기존 인스턴스를 활용하는 struct update

struct update syntax로 어떤 인스턴스에서 특정 값만 변경한 새 인스턴스를 생성하는 것도 가능합니다

fn main() {
    // --snip--

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

..와 기존 인스턴스 이름은 항상 맨 아래 라인에 와야 합니다.

이 문법은 move를 전제하고 있기 때문에, String 타입 같은 힙 메모리 값을 move했으면 이전 변수는 사라진다.

위 코드에서는 user1을 더는 사용할 수 없습니다.

하지만, 스택에 저장하는 값들만 업데이트했다면, 이 값들은 복사되기 때문에 두 변수 모두 사용가능합니다.

필드 이름이 없는 tuple struct

tuple strict는 이름만 짓고 필드 이름은 생략해도 될 때 사용합니다.

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

위와 같이, 같은 타입 형태를 가져도 이름이 다르니 다른 인스턴스가 됩니다.

사용법은 튜플과 동일합니다.

필드가 없는 unit-like struct

unit-like struct는 아무 필드도 없는 struct를 정의하는 방법입니다.

이 기능을 사용하는 것에 대해서는 차차 알아볼 것입니다.

필드에 레퍼런스 사용

이번 포스트에서 다루지 않았지만, 필드에 레퍼런스 타일을 사용하고 싶다면 lifetime을 지정해주어야 합니다

이에 대해서는 알으로 알아볼 것입니다.