खोज…


वाक्य - विन्यास

  • संरचना Foo {फ़ील्ड 1: टाइप 1, फ़ील्ड 2: टाइप 2}
  • चलो फू = फू {फ़ील्ड 1: टाइप 1 :: नया (), फ़ील्ड 2: टाइप 2 :: नया ()};
  • संरचना बार (टाइप 1, टाइप 2); // ट्यूपल प्रकार
  • चलो _ = बार (टाइप 1 :: नया (), टाइप 2 :: नया ());
  • संरचना बाज; // इकाई की तरह प्रकार
  • चलो _ = बाज;
  • Foo {फ़ील्ड 1, ..} = फू; / / फ़ील्ड 1 पैटर्न मिलान द्वारा निकालें
  • Foo {फ़ील्ड 1: x, ..} = फू; // एक्स के रूप में फ़ील्ड 1 निकालें
  • let foo2 = Foo {field1: Type1 :: new (), .. foo}; // मौजूदा से निर्माण
  • इम्पू फू {fn फिडेल (एंड सेल्फ) {}} // फू के लिए उदाहरण विधि घोषित करें
  • इम्पू फू {एफएन ट्वीक (और म्युट सेल्फ) {}} // फू के लिए म्यूटेबल इंस्टेंस विधि घोषित करें
  • इम्पू फू {fn डबल (सेल्फ) {}} // फू के लिए खुद की इंस्टेंस इंस्टेंस विधि घोषित करें
  • इम्पू फ़ू {fn new () {}} // फ़ू के लिए संबद्ध विधि की घोषणा करें

संरचनाओं को परिभाषित करना

जंग में संरचनाएं का उपयोग कर परिभाषित कर रहे हैं struct कीवर्ड। संरचना का सबसे आम रूप में नामित क्षेत्रों का एक सेट होता है:

struct Foo {
    my_bool: bool,
    my_num: isize,
    my_string: String,
}

उपरोक्त तीन क्षेत्रों के साथ एक struct घोषणा करता है: my_bool , my_num , और my_string , क्रमशः bool , isize , और String

रस्ट में struct एस बनाने का एक और तरीका है एक ट्यूपल स्ट्रक्चर बनाना:

struct Bar (bool, isize, String);

यह एक नए प्रकार को परिभाषित करता है, Bar , जिसमें तीन अनाम फ़ील्ड हैं, उस क्रम में bool , isize , और String । इसे न्यूटाइप पैटर्न के रूप में जाना जाता है, क्योंकि यह एक विशेष प्रकार के लिए प्रभावी रूप से एक नया "नाम" पेश करता है। हालाँकि, यह type कीवर्ड के उपयोग से निर्मित उपनामों की तुलना में अधिक शक्तिशाली तरीके से करता है; Bar यहां पूरी तरह से कार्यात्मक प्रकार है, जिसका अर्थ है कि आप इसके लिए अपने तरीके लिख सकते हैं (नीचे)।

अंत में, बिना फ़ील्ड वाले struct को घोषित करें, जिसे इकाई जैसी संरचना कहा जाता है:

struct Baz;

यह मॉकिंग या टेस्टिंग के लिए उपयोगी हो सकता है (जब आप किसी विशेषता को तुच्छ रूप से लागू करना चाहते हैं), या एक मार्कर प्रकार के रूप में। सामान्य तौर पर, हालांकि, आपको कई यूनिट जैसी संरचना में आने की संभावना नहीं है।

ध्यान दें कि Rust में struct क्षेत्र डिफ़ॉल्ट रूप से सभी निजी हैं - अर्थात, वे मॉड्यूल के बाहर कोड से एक्सेस नहीं किए जा सकते हैं जो प्रकार को परिभाषित करता है। आप उस क्षेत्र को सार्वजनिक रूप से सुलभ बनाने के लिए pub कीवर्ड के साथ एक फ़ील्ड को उपसर्ग कर सकते हैं। इसके अलावा, struct प्रकार स्वयं निजी है। अन्य मॉड्यूलों को प्रकार उपलब्ध कराने के लिए, pub साथ struct परिभाषा को भी उपसर्ग करना चाहिए:

pub struct X {
    my_field: bool,
    pub our_field: bool,
}

संरचना मूल्यों का निर्माण और उपयोग करना

निम्नलिखित struct परिभाषाओं पर विचार करें:

struct Foo {
    my_bool: bool,
    my_num: isize,
    my_string: String,
}
struct Bar (bool, isize, String);
struct Baz;

इन प्रकारों के लिए नए संरचना मूल्यों का निर्माण सीधा है:

let foo = Foo { my_bool: true, my_num: 42, my_string: String::from("hello") };
let bar = Bar(true, 42, String::from("hello"));
let baz = Baz;

एक संरचना का उपयोग क्षेत्रों का उपयोग . :

assert_eq!(foo.my_bool, true);
assert_eq!(bar.0, true); // tuple structs act like tuples

एक संरचना के लिए एक परिवर्तनशील बंधन अपने क्षेत्रों को उत्परिवर्तित कर सकता है:

let mut foo = foo;
foo.my_bool = false;
let mut bar = bar;
bar.0 = false;

Rust के पैटर्न-मिलान क्षमताओं का उपयोग किसी struct अंदर struct लिए भी किया जा सकता है:

// creates bindings mb, mn, ms with values of corresponding fields in foo
let Foo { my_bool: mb, my_num: mn, my_string: ms } = foo;
assert_eq!(mn, 42);
// .. allows you to skip fields you do not care about
let Foo { my_num: mn, .. } = foo;
assert_eq!(mn, 42);
// leave out `: variable` to bind a variable by its field name
let Foo { my_num, .. } = foo;
assert_eq!(my_num, 42);

या रस्ट के सिंटैक्स के साथ "टेम्पलेट" के रूप में दूसरी संरचना का उपयोग करके एक संरचना बनाएं:

let foo2 = Foo { my_string: String::from("world"), .. foo };
assert_eq!(foo2.my_num, 42);

संरचना के तरीके

एक struct पर तरीकों घोषित करने के लिए (यानी, कार्यों कि "पर" कहा जा सकता है struct , या उस के मूल्यों struct प्रकार), एक बनाने impl ब्लॉक:

impl Foo {
    fn fiddle(&self) {
        // "self" refers to the value this method is being called on
        println!("fiddling {}", self.my_string);
    }
}

// ...
foo.fiddle(); // prints "fiddling hello"

&self यहां struct Foo उदाहरण के लिए एक अपरिवर्तनीय संदर्भ को इंगित करता है struct Foo fiddle विधि को लागू करने के लिए आवश्यक है। यदि हम उदाहरण को संशोधित करना चाहते हैं (जैसे कि इसके किसी एक क्षेत्र को बदलना), तो हम इसके बजाय एक &mut self (जैसे, एक परस्पर संदर्भ) लेंगे:

impl Foo {
    fn tweak(&mut self, n: isize) {
        self.my_num = n;
    }
}

// ...
foo.tweak(43);
assert_eq!(foo.my_num, 43);

अंत में, हम भी इस्तेमाल कर सकते हैं self (एक की कमी ध्यान दें & रिसीवर के रूप में)। यह कॉल करने वाले के स्वामित्व की आवृत्ति की आवश्यकता है, और विधि को कॉल करते समय आवृत्ति को स्थानांतरित करने का कारण होगा। यह उपयोगी हो सकता है अगर हम उपभोग करना, नष्ट करना, या अन्यथा मौजूदा उदाहरण को पूरी तरह से बदलना चाहते हैं। इस तरह के उपयोग-मामले का एक उदाहरण "चैनिंग" तरीके प्रदान करना है:

impl Foo {
    fn double(mut self) -> Self {
        self.my_num *= 2;
        self
    }
}

// ...
foo.my_num = 1;
assert_eq!(foo.double().double().my_num, 4);

ध्यान दें कि हमने म्यूट के साथ self को भी उपसर्ग किया है ताकि हम इसे फिर से वापस करने से पहले self को mut सकें। double विधि का रिटर्न प्रकार भी कुछ स्पष्टीकरण का वारंट करता है। एक impl ब्लॉक के अंदर Self उस प्रकार को संदर्भित करता है जो impl इस मामले में लागू होता है ( Foo )। यहां, यह ज्यादातर प्रकार के हस्ताक्षर को फिर से टाइप करने से बचने के लिए एक उपयोगी शॉर्टहैंड है, लेकिन लक्षणों में, इसका उपयोग अंतर्निहित प्रकार को संदर्भित करने के लिए किया जा सकता है जो किसी विशेष लक्षण को लागू करता है।

संबंधित struct को घोषित करने के लिए (आमतौर पर अन्य भाषाओं में "क्लास विधि" के रूप में संदर्भित) एक struct बस self तर्क को छोड़ दें। इस तरह के तरीकों को struct प्रकार पर कहा जाता है, इसके उदाहरण पर नहीं:

impl Foo {
    fn new(b: bool, n: isize, s: String) -> Foo {
        Foo { my_bool: b, my_num: n, my_string: s }
    }
}

// ...
// :: is used to access associated members of the type
let x = Foo::new(false, 0, String::from("nil"));
assert_eq!(x.my_num, 0);

ध्यान दें कि संरचना विधियों को केवल वर्तमान मॉड्यूल में घोषित किए गए प्रकारों के लिए परिभाषित किया जा सकता है। इसके अलावा, खेतों की तरह, सभी संरचना विधियां डिफ़ॉल्ट रूप से निजी हैं, और इस प्रकार केवल एक ही मॉड्यूल में कोड द्वारा बुलाया जा सकता है। आप उन्हें कहीं से कॉल करने योग्य बनाने के लिए pub कीवर्ड के साथ परिभाषाओं को उपसर्ग कर सकते हैं।

सामान्य संरचनाएँ

संरचनाओं को एक या अधिक प्रकार के मापदंडों पर सामान्य बनाया जा सकता है। इन प्रकारों को संदर्भित किया जाता है <> जब प्रकार का संदर्भ दिया जाता है:

struct Gen<T> {
    x: T,
    z: isize,
}

// ...
let _: Gen<bool> = Gen{x: true, z: 1};
let _: Gen<isize> = Gen{x: 42, z: 2};
let _: Gen<String> = Gen{x: String::from("hello"), z: 3};

अल्पविराम का उपयोग करके कई प्रकार दिए जा सकते हैं:

struct Gen2<T, U> {
    x: T,
    y: U,
}

// ...
let _: Gen2<bool, isize> = Gen2{x: true, y: 42};

प्रकार पैरामीटर प्रकार का एक हिस्सा है, इसलिए एक ही आधार प्रकार के दो चर, लेकिन विभिन्न मापदंडों के साथ, विनिमेय नहीं हैं:

let mut a: Gen<bool> = Gen{x: true, z: 1};
let b: Gen<isize> = Gen{x: 42, z: 2};
a = b; // this will not work, types are not the same
a.x = 42; // this will not work, the type of .x in a is bool

यदि आप एक फ़ंक्शन लिखना चाहते हैं जो किसी भी प्रकार के पैरामीटर असाइनमेंट की परवाह किए बिना एक struct स्वीकार करता है, तो उस फ़ंक्शन को भी सामान्य बनाने की आवश्यकता होगी:

fn hello<T>(g: Gen<T>) {
    println!("{}", g.z); // valid, since g.z is always an isize
}

लेकिन क्या होगा अगर हम एक फ़ंक्शन लिखना चाहते हैं जो हमेशा gx प्रिंट कर सकता है? हमें T को एक प्रकार का होना प्रतिबंधित करना चाहिए जिसे प्रदर्शित किया जा सकता है। हम इसे प्रकार सीमा के साथ कर सकते हैं:

use std::fmt;
fn hello<T: fmt::Display>(g: Gen<T>) {
    println!("{} {}", g.x, g.z);
}

hello फंक्शन अब केवल Gen इंस्टेंस के लिए परिभाषित किया जाता है, जिसका T टाइप fmt::Display । यदि हमने उदाहरण के लिए एक Gen<(bool, isize)> में पास करने की कोशिश की, तो कंपाइलर शिकायत करेगा कि hello उस प्रकार से परिभाषित नहीं है।

हम यह भी के प्रकार के मानकों के आधार पर सीधे प्रकार सीमा का उपयोग कर सकते struct संकेत मिलता है कि आप केवल उस का निर्माण कर सकते struct कुछ प्रकार के लिए:

use std::hash::Hash;
struct GenB<T: Hash> {
    x: T,
}

किसी भी फ़ंक्शन जो एक GenB तक पहुंच है, अब जानता है कि x के प्रकार Hash लागू करता है, और इस प्रकार वे कॉल कर सकते हैं। .x.hash() । एक ही पैरामीटर के लिए कई प्रकार की सीमाएं उन्हें + से अलग करके दी जा सकती हैं।

फ़ंक्शंस के लिए समान, where कीवर्ड का उपयोग करके <> बाद प्रकार सीमा रखी जा सकती है:

struct GenB<T> where T: Hash {
    x: T,
}

इसका एक ही अर्थ है, लेकिन जब आपके पास जटिल सीमा होती है, तो हस्ताक्षर को पढ़ना और प्रारूपित करना आसान बना सकता है।

प्रकार पैरामीटर struct तरीकों और संबंधित तरीकों के लिए भी उपलब्ध हैं:

// note the <T> parameter for the impl as well
// this is necessary to say that all the following methods only
// exist within the context of those type parameter assignments
impl<T> Gen<T> {
    fn inner(self) -> T {
        self.x
    }
    fn new(x: T) -> Gen<T> {
        Gen{x: x}
    }
}

यदि आपके पास Gen के T पर प्रकार की सीमाएं हैं, तो उन्हें भी impl प्रकार के सीमा में परिलक्षित होना चाहिए। आप यह भी कर सकते हैं impl कहना है कि किसी दिए गए विधि केवल तभी प्रकार को संतुष्ट करता है एक विशेष संपत्ति मौजूद है सीमा तंग:

impl<T: Hash + fmt::Display> Gen<T> {
    fn show(&self) {
        println!("{}", self.x);
    }
}

// ...
Gen{x: 42}.show(); // works fine
let a = Gen{x: (42, true)}; // ok, because (isize, bool): Hash
a.show(); // error: (isize, bool) does not implement fmt::Display


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow