Rustのtraitは抽象クラスではない

# スーパー忙しい人向け
- Rustの`trait`は`abstract class`ではない。
- `Is XXX`ではない！`Can XXX`だ！

# 抽象クラスについて
この記事で扱う**抽象クラス**とは、Java等に存在する`abstract class`のことを指し示しています。  
抽象的なクラスを定義する概念であり、`〇〇はXXである。`の`はXXである。`の部分が抽象クラスという体でこの記事を執筆しています。  
この記事はJavaや`abstract class`、およびその利用者を中傷する意図はありません。

# こんなtrait宣言していませんか？

```rs
// 例
trait Person {
    fn walk(&self);
    fn run(&self) -> Result<(), PersonError>;
    fn speak(&self, content);
    fn sleep(&mut self) -> Result<bool, PersonError>;
}
```

**これ、間違っています。**  

それ、`trait`を抽象クラスと**勘違い**していませんか？  
`trait`は**何が出来るか**を示すためのものです。

---

```rs
// 例
trait IoStream {
    type Output;

    fn input(&mut self) -> Result<(), IoStreamError>;
    fn output(&self) -> Result<Self::Output, IoStreamError>;
}

#[derive(Default)]
struct FileStream {
    buffer: Vec<u8>,
};

impl IoStream for FileStream {
    type Output = Vec<u8>;
    
    fn input(&mut self) -> Result<(), IoStreamError> {
        fsys::read_file(&mut self.buffer).map_err(|e| error_handle!(e))
    }

    fn output(&self) -> Result<Self::Output, IoStreamError> {
        fsys::write_file(&self.buffer).map_err(|e| error_handle!(e))
    }
}

#[derive(Default)]
struct ShellStream {
    attach_shell: Shell,
};

impl IoStream for ShellStream {
    type Output = String;

    fn input(&mut self) -> Result<(), IoStreamError> {
        let handler = self.attach_shell.blocking();
        handler.pipe().map_err(|e| error_handle!(e))
    }

    fn output(&self) -> Result<Self::Output, IoStreamError> {
        self.attach_shell.out().map_err(|e| error_handle!(e))
    }
}
```

**これ、間違っています。**  

ioとくくられているだけでInputとOutputは**別の目的**で利用します。  
1つの`trait`の利用目的は1つに定めるべきです。  

# どうすればいいのか？

**1つの`trait`は1種類の機能のみを持たせるべきです。**  

なぜなら、`trait`とは`〇〇が出来る`ということを宣言するための機能であるためです。  
決して`〇〇である`ということでは**ありません**！  

:::note warn
`〇〇である`ということ
```rs
trait Person { ... }

struct John;

// John is Person
impl Person for John { ... }
```
:::

これは主に保守性に影響します。  
特に根本的な違いがある処理を`trait`でまとめて共通化などをすると起こりやすく、大本の`trait`に依存した構造になるため規模が大きくなると改変がとても難しくなります。  

:::note warn
難しくなっちゃった例(ChatGPTで生成しました)
```rs
trait Entity {
    fn name(&self) -> &str;
    fn move_to(&mut self, x: i32, y: i32);
    fn attack(&mut self, target: &mut dyn Entity) -> Result<(), String>;
    fn take_damage(&mut self, amount: i32);
    fn speak(&self, message: &str);
    fn save_state(&self) -> String;
    fn load_state(&mut self, data: &str);
}

struct Player {
    name: String,
    x: i32,
    y: i32,
    hp: i32,
}

// Player is Entity
// 実装は考えたくもない
impl Entity for Player { ... }
```
:::

要するに**抽象クラスと同じ使い方をすると危険ということです。**  

より素晴らしい方法に修正するのは簡単です。  
対象の持つすべてのメソッドを1つずつ分解し、既存の`trait`やクレート内の共通化出来る機能でくくって実装するだけです。  

`trait`は所詮機能なので、抽象クラスのように**実装を前提としたロジックにする必要はありません！**  
保守作業で共通化出来そうにないと思えば、実装を外して独自実装に切り替えることが出来ます！  

## 具体例

上記の間違いを修正してみます。  
```rs
trait Person {
    fn walk(&self);
    fn run(&self) -> Result<(), PersonError>;
    fn speak(&self, content);
    fn sleep(&mut self) -> Result<bool, PersonError>;
}
```

`Person`は見る限り人の**定義**であり、`trait`としてはふさわしくありません。  
機能ごとに分割した`trait`として定義しましょう。  

```rs
trait MoveFoot {
    fn walk(&self);
    fn run(&self) -> Result<(), PersonError>;
}

trait Speak {
    fn speak(&self, content);
}

trait Sleep {
    fn sleep(&mut self) -> Result<bool, PersonError>;
}

struct Person;

impl MoveFoot for Person { ... }
impl Speak for Person { ... }
impl Sleep for Person { ... }
```

---

```rs
trait IoStream {
    type Output;

    fn input(&mut self) -> Result<(), IoStreamError>;
    fn output(&self) -> Result<Self::Output, IoStreamError>;
}

#[derive(Default)]
struct FileStream {
    buffer: Vec<u8>,
};

impl IoStream for FileStream {
    type Output = Vec<u8>;
    
    fn input(&mut self) -> Result<(), IoStreamError> {
        fsys::read_file(&mut self.buffer).map_err(|e| error_handle!(e))
    }

    fn output(&self) -> Result<Self::Output, IoStreamError> {
        fsys::write_file(&self.buffer).map_err(|e| error_handle!(e))
    }
}

#[derive(Default)]
struct ShellStream {
    attach_shell: Shell,
};

impl IoStream for ShellStream {
    type Output = String;

    fn input(&mut self) -> Result<(), IoStreamError> {
        let handler = self.attach_shell.blocking();
        handler.pipe().map_err(|e| error_handle!(e))
    }

    fn output(&self) -> Result<Self::Output, IoStreamError> {
        self.attach_shell.out().map_err(|e| error_handle!(e))
    }
}
```

I/Oが両方必要な場面は限られます。  
I/Oにまとめるのはモジュール単位で十分です。

```rs
trait Input {
    fn input(&mut self) -> Result<(), IoStreamError>;
}

trait Output {
    type Output;

    fn output(&self) -> Result<Self::Output, IoStreamError>;
}

impl Input for T { ... }
impl Output for T { ... }

impl Input for S { ... }
impl Output for S { ... }
```

---

ChatGPTに生成してもらったやつです。
```rs
trait HasName {
    fn name(&self) -> &str;
}

trait Movable {
    fn move_to(&mut self, x: i32, y: i32);
}

trait Combat {
    fn attack(&mut self, target: &mut dyn TakeDamage) -> Result<(), String>;
}

trait TakeDamage {
    fn take_damage(&mut self, amount: i32);
}

trait Speak {
    fn speak(&self, message: &str);
}

trait SaveLoad {
    fn save_state(&self) -> String;
    fn load_state(&mut self, data: &str);
}

struct Player {
    name: String,
    x: i32,
    y: i32,
    hp: i32,
}

impl HasName for Player {
    fn name(&self) -> &str {
        &self.name
    }
}

impl Movable for Player {
    fn move_to(&mut self, x: i32, y: i32) {
        self.x = x;
        self.y = y;
    }
}

impl Combat for Player {
    fn attack(&mut self, target: &mut dyn TakeDamage) -> Result<(), String> {
        target.take_damage(10);
        Ok(())
    }
}

impl TakeDamage for Player {
    fn take_damage(&mut self, amount: i32) {
        self.hp -= amount;
    }
}

impl Speak for Player {
    fn speak(&self, message: &str) {
        println!("{} says: {}", self.name, message);
    }
}

impl SaveLoad for Player {
    fn save_state(&self) -> String {
        format!("{},{},{},{}", self.name, self.x, self.y, self.hp)
    }

    fn load_state(&mut self, data: &str) {
        let parts: Vec<&str> = data.split(',').collect();
        self.name = parts[0].to_string();
        self.x = parts[1].parse().unwrap();
        self.y = parts[2].parse().unwrap();
        self.hp = parts[3].parse().unwrap();
    }
}
```
私が間違っているかもしれません。

# stdのtrait

以下、`std`で宣言されている一部の`trait`の簡単な紹介です。

## `Display`

https://doc.rust-lang.org/std/fmt/trait.Display.html

```rs
pub trait Display {
    // Required method
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
```

`Display`を実装すると、フォーマット可能であることを宣言できます。  
`println`マクロや`format`マクロで直接利用するには`Display`が実装されている必要があります。

## `ToString`

https://doc.rust-lang.org/std/string/trait.ToString.html

```rs
pub trait ToString {
    // Required method
    fn to_string(&self) -> String;
}
```

`ToString`を実装すると、`String`に変換可能であることを宣言できます。  
また、`Display`を実装すると自動で実装されるので、必要な場合のみ`ToString`を実装してください。

## `Write` / `Read`

https://doc.rust-lang.org/std/io/trait.Write.html

https://doc.rust-lang.org/std/io/trait.Read.html

```rs
pub trait Write {
    // Required methods
    fn write(&mut self, buf: &[u8]) -> Result<usize>;
    fn flush(&mut self) -> Result<()>;

    // Provided methods
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { ... }
    fn is_write_vectored(&self) -> bool { ... }
    fn write_all(&mut self, buf: &[u8]) -> Result<()> { ... }
    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<()> { ... }
    fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()> { ... }
    fn by_ref(&mut self) -> &mut Self
       where Self: Sized { ... }
}

pub trait Read {
    // Required method
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

    // Provided methods
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> { ... }
    fn is_read_vectored(&self) -> bool { ... }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { ... }
    fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { ... }
    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { ... }
    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { ... }
    fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<()> { ... }
    fn by_ref(&mut self) -> &mut Self
       where Self: Sized { ... }
    fn bytes(self) -> Bytes<Self>
       where Self: Sized { ... }
    fn chain<R: Read>(self, next: R) -> Chain<Self, R>
       where Self: Sized { ... }
    fn take(self, limit: u64) -> Take<Self>
       where Self: Sized { ... }
}
```

なんらかの書き込み/読み込み手段を持つことを宣言できます。  
それぞれ単一の目的で実装されるため、必要な方もしくは両方を選択して利用できます。  
`Write`は`write`マクロなどに利用されます。(`Display`の実装など)  

# 最後に

この記事は特にこれといった根拠なく執筆しているので、間違っている部分が含まれている可能性があります。  
rust-by-exampleを読んで不安になりました。