トレイトの定義
共有される振る舞い
「トレイトの定義」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全4レッスンが含まれています。
トレイトとは
トレイトは共通の振る舞い、つまり型が実装できるメソッドの集合を定義します。他の言語におけるインターフェースに似ています。
トレイトを使うと、異なる型が共通の契約に従えるようになります。
トレイトの宣言
traitキーワードの後にメソッドシグネチャを記述します。シグネチャによって、実装する型が提供すべき内容を宣言します。
trait Greet {
fn hello(&self) -> String;
}
fn main() {
println!("trait declared");
}トレイトの実装
impl TraitName for Typeを使ってメソッドを提供します。シグネチャはトレイトと完全に一致していなければなりません。
trait Greet {
fn hello(&self) -> String;
}
struct Dog;
impl Greet for Dog {
fn hello(&self) -> String {
String::from("Woof")
}
}
fn main() {
let d = Dog;
println!("{}", d.hello());
}1つのトレイトに複数の型
複数の型が同じトレイトを、それぞれ独自の方法で実装できます。これにより、互いに関係のない型の間でも振る舞いを統一できます。
trait Greet { fn hello(&self) -> String; }
struct Dog;
struct Cat;
impl Greet for Dog { fn hello(&self) -> String { String::from("Woof") } }
impl Greet for Cat { fn hello(&self) -> String { String::from("Meow") } }
fn main() {
println!("{}", Dog.hello());
println!("{}", Cat.hello());
}関数パラメーターとしてのトレイト
impl Trait構文を使うと、そのトレイトを実装する任意の型を受け取れます。具体的な型を知らなくても、関数は同じように動作します。
trait Greet { fn hello(&self) -> String; }
struct Dog;
impl Greet for Dog { fn hello(&self) -> String { String::from("Woof") } }
fn announce(g: &impl Greet) {
println!("It says: {}", g.hello());
}
fn main() {
announce(&Dog);
}ジェネリクスのトレイト境界
トレイト境界を使うと、ジェネリック型が特定のトレイトを実装していることを要求できます。これにより、関数内でそのトレイトのメソッドを使えるようになります。
trait Greet { fn hello(&self) -> String; }
struct Cat;
impl Greet for Cat { fn hello(&self) -> String { String::from("Meow") } }
fn shout<T: Greet>(g: &T) {
println!("{}!", g.hello().to_uppercase());
}
fn main() {
shout(&Cat);
}+による複数の境界
+を使うと、複数のトレイトを同時に要求できます。ここでは、値が独自のトレイトと標準のCloneの両方を実装している必要があります。
trait Named { fn name(&self) -> String; }
#[derive(Clone)]
struct Item { label: String }
impl Named for Item {
fn name(&self) -> String { self.label.clone() }
}
fn describe<T: Named + Clone>(t: &T) {
let copy = t.clone();
println!("named {}", copy.name());
}
fn main() {
describe(&Item { label: String::from("box") });
}where句
境界が多い場合は、where句を使うと制約をシグネチャの下に移せるため、シグネチャを読みやすく保てます。
use std::fmt::Debug;
fn print_all<T>(items: &[T])
where
T: Debug,
{
for it in items {
println!("{:?}", it);
}
}
fn main() {
print_all(&[1, 2, 3]);
}トレイトには複数のメソッドを定義できる
トレイトには複数のメソッドを宣言できます。実装する型は、必要なメソッドをすべて提供し、完全な振る舞いの集合を備えなければなりません。
trait Shape {
fn area(&self) -> f64;
fn name(&self) -> String;
}
struct Square { side: f64 }
impl Shape for Square {
fn area(&self) -> f64 { self.side * self.side }
fn name(&self) -> String { String::from("square") }
}
fn main() {
let s = Square { side: 3.0 };
println!("{} area {}", s.name(), s.area());
}トレイトが重要な理由
トレイトを使うと、継承なしでポリモーフィズムを実現できます。ジェネリクス、演算子のオーバーロード(Add)、フォーマット(Display)など、標準ライブラリの多くの機能を支えています。
トレイトはRustの抽象化モデルの中心です。
コヒーレンスルール
孤児ルールでは、トレイトまたは型のどちらかを自分が所有している場合にのみ、その型に対してトレイトを実装できます。これにより、クレート間で実装が衝突するのを防ぎます。
理解度チェック
トレイトについての理解度を確認しましょう。
まとめ
トレイトを定義して使う方法を学びました。
traitで共通の振る舞いを宣言しますimpl Trait for Typeでメソッドを提供します- トレイト境界(
T: Trait、+、where)でジェネリクスを制約します - 孤児ルールによって実装の一貫性が保たれます
よくある質問
「トレイトの定義」レッスンは無料ですか?
はい。「トレイトの定義」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全4レッスンが含まれています。
「トレイトの定義」で何を学びますか?
共有される振る舞い ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「トレイトの定義」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。