နားလည်ထားရမယ့် အချက်
Struct ဆိုတာ related field များစွာကို named group တစ်ခုအဖြစ် ပေါင်းစည်းထားတဲ့ custom data type တစ်ခုဖြစ်ပြီး Lesson 4 ရဲ့ tuple နှင့် ကွာတာက field တစ်ခုစီကို name ပေးထားလို့ order အတိအကျ မမှတ်ထားဘဲ `lesson.title`, `lesson.word_count` လို readable syntax ဖြင့် access လုပ်နိုင်ပါတယ်—large data structure တွေကို tuple ဖြင့် ကိုင်တွယ်ရင် field order မှားနိုင်တဲ့ bug ကို struct field name က ကာကွယ်ပေးပါတယ်။ `impl` block ကတော့ struct type တစ်ခုအပေါ် function တွေကို associate ချိတ်ဆက်ပေးတဲ့ syntax ဖြစ်ပြီး method (ပထမဆုံး parameter အနေနဲ့ `&self`/`&mut self`/`self` ယူ) နှင့် associated function (ပထမ parameter `self` မယူ—`String::from` လို constructor pattern) ကွာခြားချက်ကို ဖော်ပြပါတယ်။ Method ကို instance ရှိမှသာ ခေါ်နိုင်ပါတယ် (`lesson.summary()`) ဒါပေမယ့် associated function ကို type name ကို တိုက်ရိုက်ခေါ်ပါတယ် (`Lesson::new(...)`)—Java/C++ ရဲ့ static method concept နှင့် ဆင်တူပါတယ်။ Struct + `impl` ရဲ့ design philosophy က object-oriented language တွေရဲ့ class concept နှင့် ရည်ရွယ်ချက်တူပေမယ့် Rust မှာ inheritance မရှိပါဘူး—behavior sharing ကို Lesson 14 ရဲ့ trait များကနေသာ ရနိုင်ပါတယ်—ဒီ constraint ကြောင့် composition-first design ကို encourage ပေးပါတယ်။ `self` ကို `&self` (borrow, read-only), `&mut self` (borrow, mutable), `self` (ownership take, method ခေါ်ပြီး instance ကို consume) သုံးမျိုးအနေနဲ့ ရွေးချယ်နိုင်တာက Lesson 6/7 ရဲ့ ownership/borrowing rule တွေကို struct method level မှာပင် ထပ်ကျင့်ပြီး ဆက်တွေ့ရမယ့် pattern တစ်ခုပါ။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Content analyzer project ရဲ့ core data structure ကို `struct LessonStat { title: String, word_count: u32, difficulty: String }` လို define မယ်—field name တွေက ကိုယ့်ဘာသာ ဖော်ပြနေလို့ downstream code ထဲမှာ readable ဖြစ်ပါတယ်။ Constructor pattern အတွက် `impl LessonStat { fn new(title: String, word_count: u32) -> Self { ... } }` associated function ကို ရေးမယ်—difficulty ကို word_count ကနေ auto-classify (Lesson 5 ရဲ့ `if` expression သုံးပြီး) လုပ်ပေးမယ်။ Read-only summary ထုတ်ပေးမယ့် method ကို `fn summary(&self) -> String { format!("{}: {} words", self.title, self.word_count) }` လို `&self` သုံးမယ်—instance ကို consume မလုပ်ဘဲ caller ဘက်က ဆက်သုံးနိုင်အောင်ပါ။
အတူတူ စမ်းရေးကြည့်မယ်
struct LessonStat {
title: String,
word_count: u32,
difficulty: String,
}
impl LessonStat {
fn new(title: String, word_count: u32) -> Self {
let difficulty = if word_count < 500 { "basic" } else { "intermediate" };
LessonStat { title, word_count, difficulty: difficulty.to_string() }
}
fn summary(&self) -> String {
format!("{} ({}): {} words", self.title, self.difficulty, self.word_count)
}
}
fn main() {
let lesson = LessonStat::new(String::from("Ownership"), 620);
println!("{}", lesson.summary());
}"Ownership (intermediate): 620 words" ကို print ထုတ်နိုင်မည်။၅ မိနစ် စမ်းကြည့်
`struct Tag { name: String, uses: u32 }` ဖန်တီးပါ—`Tag::new(name: String) -> Self` associated function (uses = 0 ကနေစ) နှင့် `increment(&mut self)` method ကို ရေးပါ—tag တစ်ခု ဖန်တီးပြီး increment နှစ်ကြိမ်ခေါ်ကာ uses count ကို print ထုတ်ပါ။
သတိလေးတစ်ချက်
Method ကို `&self` မလိုအပ်ဘဲ `self` (ownership take) ဖြင့် ရေးထားခြင်း—method ကို ခေါ်တာနဲ့ instance ကို consume လုပ်သွားလို့ caller ဘက်က ဒီ instance ကို ထပ်သုံးမရတော့ဘဲ compile error ရနိုင်ပါတယ်။
Field value ကို ပြောင်းချင်ပေမယ့် method signature ကို `&self` (read-only) အနေနဲ့ ရေးထားခြင်း—`&mut self` လိုအပ်တာကို မသတိထားမိဘဲ compile error "cannot assign to `self.field`" ကို ရင်ဆိုင်ရနိုင်ပါတယ်။