अक्सर कई चीज़ों को एक समूह में रखना और उन समूहों को एक इकाई की तरह संभालना उपयोगी होता है। Cairo में हम ऐसे समूह को स्ट्रक्ट कहते हैं, और समूह की हर चीज़ को स्ट्रक्ट का एक फील्ड। एक स्ट्रक्ट यह तय करता है कि कौन-कौन से फील्ड उपलब्ध हैं, लेकिन स्ट्रक्ट के किसी एक खास उदाहरण को इंस्टेंस कहते हैं।
इसके अलावा, स्ट्रक्ट पर मेथड बनाए जा सकते हैं, और इन मेथड को फील्ड तक पहुँच होती है। ऐसी स्थिति में स्ट्रक्ट को ही self कहा जाता है। जब कोई मेथड ref self: SomeStruct लिखता है, तो फील्ड बदले जा सकते हैं, यानी म्यूटेट किए जा सकते हैं। जब कोई मेथड self: SomeStruct या self: @SomeStruct लिखता है, तो फील्ड बदले नहीं जा सकते: वे अपरिवर्तनीय होते हैं। म्यूटेबिलिटी को नियंत्रित करने से बॉरो-चेकर को यह सुनिश्चित करने में मदद मिलती है कि Cairo में कॉन्करेंसी से जुड़ी कई तरह की गलतियाँ होती ही नहीं।
इस अभ्यास में आप एक स्ट्रक्ट पर दो तरह के मेथड लागू करेंगे। पहले को आम तौर पर गेटर कहा जाता है: ये स्ट्रक्ट के फील्ड सबके सामने खोल देते हैं, पर किसी और को उस वैल्यू को बदलने नहीं देते।
आप दूसरी तरह के मेथड भी लागू करेंगे, जिन्हें आम तौर पर सेटर कहा जाता है। ये फील्ड की वैल्यू बदल देते हैं। Cairo में सेटर बहुत आम नहीं हैं। अगर किसी फील्ड को खुलकर बदला जा सकता है, तो उसे सिर्फ पब्लिक बना देना ज़्यादा आम है। लेकिन अगर फील्ड को अपडेट करने का कोई साइड इफेक्ट हो, तो सेटर काम आते हैं।
स्ट्रक्ट struct कीवर्ड से परिभाषित किए जाते हैं। कीवर्ड के बाद उस टाइप का नाम लिखा जाता है जिसे यह स्ट्रक्ट बता रहा है, और यह नाम बड़े अक्षर से शुरू होता है:
struct Item {}
इसके बाद और टाइप स्ट्रक्ट के अंदर उसके फील्ड के रूप में जोड़े जाते हैं, और हर फील्ड का अपना टाइप होता है:
struct Item {
name: String,
weight: f32,
worth: u32,
}
एक ट्रेट उन मेथड का समूह तय करता है जिन्हें कोई टाइप लागू कर सकता है (यहाँ हम स्ट्रक्ट पर ध्यान देंगे, पर ट्रेट को इनम पर भी लागू किया जा सकता है)। जब यह ट्रेट लागू किया गया हो, तब इन मेथड को उस टाइप के इंस्टेंस पर कॉल किया जा सकता है। ट्रेट trait कीवर्ड से परिभाषित किए जाते हैं, और ट्रेट के अंदर हम वे मेथड सिग्नेचर लिखते हैं जिन्हें हम अपने टाइप में लागू कराना चाहते हैं।
trait ImplTrait {
// Define the method signature
fn new() -> Item;
}
अंत में, स्ट्रक्ट पर मेथड impl ब्लॉक के अंदर परिभाषित किए जा सकते हैं, और यह ब्लॉक तय किए गए ट्रेट को लागू करता है:
impl ItemImpl of ImplTrait {
// initializes and returns a new instance of our Item struct
fn new() -> Item {
Item {}
}
}
आप एक हेल्थ-मॉनिटरिंग सिस्टम बनाने पर काम कर रहे हैं। उसी के एक हिस्से के तौर पर आपको उपयोगकर्ताओं के स्वास्थ्य आँकड़ों का हिसाब रखना है।
शुरुआत में आपको एक impl ब्लॉक में कुछ अधूरे फंक्शन मिलेंगे, और साथ में struct की यह परिभाषा भी:
pub struct User {
name: String,
age: u32,
weight: u32,
}
आपको impl ब्लॉक में परिभाषित User struct के अधूरे मेथड पूरे करने हैं।
उदाहरण के लिए, new मेथड को User struct का एक इंस्टेंस लौटाना चाहिए, जिसमें दिए गए नाम, उम्र और वजन की वैल्यू हों।
let mut bob = User::new("Bob", 32, 72);
// Returns: a User with name "Bob", age 32, and weight 72
weight मेथड को User का वजन लौटाना चाहिए।
bob.weight();
// Returns: 72
set_age मेथड को User की उम्र तय करनी चाहिए।
bob.set_age(33);
// Updates Bob's age to 33; happy birthday Bob!
मज़े कीजिए!
Exercism पर साइन अप कीजिए और Cairo को 25 कॉन्सेप्ट68 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।