戻る

Trait Dictionary

Rust のトレイトは “トレイトとしては別物” らしい

Trait

Trait T を定義

trait T {
}

Trait S を要求する Trait T を定義
Trait S は Trait T の Supertrait
Trait T は Trait S の Subtrait

trait S {
}

trait T: S {
}

Trait R と Trait S を要求する Trait T を定義

trait R {
}

trait S {
}

trait T: R + S {
}

Clone (std::clone::Clone)

pub trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) {...}
}
#[derive(Debug)]
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };
    let t = s;

    dbg!(s);  // Error.
    dbg!(t);
}

こうすると Move された s を使ったところでエラーとなってしまうが
Clone を実装してから工夫すれば実行できる

#[derive(Clone, Debug)]
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };
    let t = &s.clone();

    dbg!(s);  //=> s = S {
              //=>     x: 1,
              //=> }
    dbg!(t);  //=> t = S {
              //=>     x: 1,
              //=> }
}

ちなみに &s.clone() は s.clone() でもいい

いま Struct S のインスタンスを s とすると

Struct S のメソッド fn method(self) {} は
s.method() でも &s.method() でも呼べる
&s.method() とした呼んだ場合は
s.method() として呼んだものとして処理される

Struct S のメソッド fn method(&self) {} は
s.method() でも &s.method() でも呼べる
s.method() とした呼んだ場合は
&s.method() として呼んだものとして処理される

Rust がよしなにしてくれる

Required:
Copy (std::marker::copy

Cloning a reference and method call syntax in Rust
[Rust] メソッド呼び出し時におけるメソッド探索の仕組み: 自動参照 & 自動参照外し及び Unsized 型強制

Copy (std::marker::Copy)

pub trait Copy: Clone {}
#[derive(Debug)]
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };
    let t = s;

    dbg!(s);  // Error.
    dbg!(t);
}

こうすると Move された s を使ったところでエラーとなってしまうが
Copy を実装すれば実行できる

#[derive(Copy, Clone, Debug)]
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };
    let t = s;

    dbg!(s);  //=> s = S {
              //=>     x: 1,
              //=> }
    dbg!(t);  //=> t = S {
              //=>     x: 1,
              //=> }
}

Copy は Clone を要求していることに注意したい

Copy を実装できない例

#[derive(Copy, Clone)]
struct S {
    x: Box<i32>,  // Error.
}

Clone は実装できる

#[derive(Clone)]
struct S {
    x: Box<i32>,
}

Requires:
Clone (std::clone::Clone

RustのCloneとCopyについての素朴な疑問

Debug (std::fmt::Debug)

pub trait Debug {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };

    dbg!(s);  // Error.
}

こうするとエラーになってしまうが
Debug を実装すれば実行できる

#[derive(Debug)]
struct S {
    x: i32,
}

fn main() {
    let s = S {
        x: 1,
    };

    dbg!(s);  //=> s = S {
              //=>     x: 1,
              //=> }
}

Deref (std::ops::Deref)

pub trait Deref {
    type Target: ?Sized;
    fn deref(&self) -> &Self::Target;
}
let b = Box::new(1);
dbg!(*b)  //=> *b = 1

これができるのは Deref のおかげ

Derefトレイトでスマートポインタを普通の参照のように扱う

Fn (std::ops::Fn)

pub trait Fn<Args>: FnMut<Args> {
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
fn main() {
    let mut n = 5;
    {
        let mut add = |x| n += x;
        add(5);
        dbg!(n);  // n = 10
    }
    dbg!(n);  // n = 10
}
fn main() {
    let mut n = 5;
    {
        let mut add = move |x| n += x;  // Copy of n occured because it is a move closure.
        add(5);  // This does not change the original value of n but changes copied value of n.
        dbg!(n);  //=> n = 5  // Original value of n.
    }
    dbg!(n);  //=> n = 5  // Original value of n.
}

Requires:
FnMut (std::ops::FnMut)

Trait std::ops::Fn
Rustのクロージャtraitについて調べた(FnOnce, FnMut, Fn)
Rust の Fn, FnMut, FnOnce の使い分け
Rustで高階関数を使う Rustのクロージャ3種を作って理解する

FnMut (std::ops::FnMut)

pub trait FnMut<Args>: FnOnce<Args> {
    extern "rust-call" fn call_mut(
        &mut self, 
        args: Args
    ) -> Self::Output;
}

Requires:
FnOnce (std::ops::FnOnce

Required:
Fn (std::ops::Fn)

Trait std::ops::FnMut

FnOnce (std::ops::FnOnce)

pub trait FnOnce<Args> {
    type Output;
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

Required:
FnMut (std::ops::FnMut)

Trait std::ops::FnOnce

From (std::convert::From)

pub trait From<T> {
    fn from(T) -> Self;
}

おなじみのやつ

let s = String::from("str");

Complementary:
Into (std::convert::Into

Future (std::future::Future)

pub trait Future {
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

Enum Poll は

pub enum Poll<T> {
    Ready(T),
    Pending,
}

Rust でお気楽非同期プログラミング
Rustの非同期プログラミングをマスターする
非同期 Rust パターン

Into (std::convert::Into)

pub trait Into<T> {
    fn into(self) -> T;
}

変換先の型を推論して,よしなに変換してくれる。強い

たとえば

web_sys::console::log_1(data_1: &JsValue)

に参照を渡したいとき &JsValue ってなにとなるが,とりあえず into() しておけば,勝手にうまいことやってくれるかもしれない

console::log_1(&hoge.into());

Complementary:
From (std::convert::From)

From and Into

戻る

↓ 故障中