Tomoki Ota's Blog

article icon

【Rust】コンストラクタ

作成日 

goとrustのコンストラクタ

Goではコンストラクタがないので、NewXXXというファクトリ関数を作って初期化します。

type User struct {
    Name string
    Age  int
}
 
func NewUser(name string, age int) User {
    return User{
        Name: name,
        Age:  age,
    }
}
 
func main() {
    user := NewUser("太郎", 20)
    fmt.Println(user)
}

RustではGoと同じく組み込みのコンストラクタが存在しないので、Go同様ファクトリ関数でコンストラクタを実装することができる。

#[derive(Debug)]
struct User {
    name: String,
    age: u32,
}
 
impl User {
    fn new(name: &str, age: u32) -> Self {
        User {
            name: name.to_string(),
            age,
        }
    }
}
 
fn main() {
    let user = User::new("太郎", 20);
    println!("{:?}", user); // User { name: "太郎", age: 20 }
}

# [derive(Debug)]については https://qiita.com/tarou-imokenpi/items/2a606badb6cdf959a1e1 を参考にしてください。

ビルトインコンストラクタ

RustにはC++と異なってCopyDefaultAssignmentMoveなどのようなビルトインコンストラクタの機能はない。

Defaultコンストラスタに関しては、Defaultトレイトが同等の機能を提供している。しかし、このトレイトを使用するのは驚くほどレアである。なぜなら、 変数は暗黙には初期化されないからである。 Default は、 一般的にジェネリックプログラミングでのみ有効。

Default trait

favicon of doc.rust-lang.org

Defaultトレイトはdefault()を持つ。

Defaultトレイト
pub trait Default: Sized {
    fn default() -> Self;
}

以下のようにenumでも使用できる

#[derive(Debug)]
#[allow(dead_code)]
struct User {
    name: String,
    age: u32,
}
 
impl Default for User {
    fn default() -> Self {
        Self {
            name: String::from("Anonymous"),
            age: 0,
        }
    }
}
 
fn main() {
    let user: User = Default::default();
    println!("{:?}", user);
}

他にもStringや&strでもDefaultトレイトを持っているので、使用することができる。

fn main() {
    let s = String::default();
    println!("{}", s);
 
    let int = i32::default();
    println!("{}", int); // 0
 
    let str: &str = Default::default();
    println!("{}", str); 
}

Defaultマクロ

Defaultマクロを用いると、手動でDefault トレイトを実装しなくても、型に対して自動的にDefaultトレイトの実装を生成してくれる。

#[derive(Default)]
struct User {
    name: String,
    age: u32,
}
 
fn main(){
    let user : User = Default::default(); 
    println!("{:?}", user); // User { name: "", age: 0 }
}

再帰的に使うことも可能。

#[derive(Debug, Default)]
struct User {
    name: String,
    age: u32,
}
 
#[derive(Debug, Default)]
struct Family {
    mother: User,
    father: User,
    child: User,
}
 
fn main() {
    let family: Family = Default::default();
    println!("{:?}", family);
}

実行すると以下のようになる。

Family { mother: User { name: "", age: 0 }, father: User { name: "", age: 0 }, child: User { name: "", age: 0 } }

また、enumの場合は以下のようになる。

#[derive(Default)]
enum Kind {
    #[default]
    A,
    B,
    C,
}

参考文献

  1. コンストラクタ
この記事をシェアするx icon
アイコン画像
Tomoki Ota

フルスタックエンジニア。Goが好き。趣味はカメラと旅行です📷