कक्षा में संरचना क्यों चुनें?


476

जावा बैकग्राउंड से आने वाली स्विफ्ट के साथ खेलते हुए, आप क्लास की बजाय स्ट्रक्चर क्यों चुनना चाहेंगे? लगता है कि वे एक ही चीज़ हैं, जिसमें एक संरचना कम कार्यक्षमता प्रदान करती है। फिर इसे क्यों चुना?


11
संरचनाएं हमेशा तब कॉपी की जाती हैं जब वे आपके कोड में पास हो जाती हैं, और संदर्भ गिनती का उपयोग नहीं करती हैं। स्रोत: developer.apple.com/library/prerelease/ios/documentation/swift/…
holex

4
मैं कहूंगा कि डेटा को होल्ड करने के लिए स्ट्रक्चर्स अधिक उपयुक्त हैं, न कि लॉजिक। जावा शब्दों में बोलने के लिए, "मूल्य ऑब्जेक्ट" के रूप में संरचना की कल्पना करें।
विंसेंट गेरसी

6
मैं इस पूरी बातचीत में हैरान हूं कि कॉपी-ऑन-लिखने उर्फ आलसी कॉपी का कोई सीधा उल्लेख नहीं है । स्ट्रक्चर कॉपी प्रदर्शन के बारे में कोई भी चिंता ज्यादातर इस डिजाइन के कारण है।
डेविड जेम्स

3
एक वर्ग पर एक संरचना का चयन करना एक राय का विषय नहीं है। एक या दूसरे को चुनने के लिए विशिष्ट कारण हैं।
डेविड जेम्स

मैं अत्यधिक यह देखने की सलाह देता हूं कि ऐरे थ्रेडसेफ़ क्यों नहीं है । यह संबंधित है क्योंकि Arrays और Structs दोनों मूल्य प्रकार हैं। यहां सभी उत्तरों में उल्लेख है कि संरचना / सरणियों / मूल्य प्रकारों के साथ थ्रेड सुरक्षा मुद्दा कभी नहीं होगा, लेकिन एक कोने का मामला है जिसमें आप करेंगे।
हनी

जवाबों:


548

बहुत लोकप्रिय WWDC 2015 टॉक प्रोटोकॉल ओरिएंटेड प्रोग्रामिंग इन स्विफ्ट ( वीडियो , ट्रांसक्रिप्ट ) के अनुसार, स्विफ्ट कई विशेषताओं को प्रदान करता है जो कई परिस्थितियों में कक्षाओं की तुलना में बेहतर बनाते हैं।

संरचनाएं बेहतर होती हैं यदि वे अपेक्षाकृत छोटे और मैथुन योग्य हों क्योंकि नकल करना उसी तरह से कई संदर्भों की तुलना में सुरक्षित होता है जैसे कि कक्षाओं के साथ होता है। यह विशेष रूप से महत्वपूर्ण है जब एक चर के आसपास से गुजर रहा है कई वर्गों और / या एक बहुआयामी वातावरण में। यदि आप हमेशा अपने चर की एक प्रति अन्य स्थानों पर भेज सकते हैं, तो आपको कभी भी इस बात की चिंता नहीं करनी चाहिए कि आपके चर का मूल्य आपके नीचे बदल रहा है।

स्ट्रक्चर्स के साथ, एक चर के एक उदाहरण को एक्सेस / संशोधित करने के लिए मेमोरी लीक या मल्टीपल थ्रेड रेसिंग के बारे में चिंता करने की बहुत कम आवश्यकता होती है। (अधिक तकनीकी रूप से दिमाग के लिए, इसका अपवाद तब होता है जब किसी बंद के अंदर एक संरचना को कैप्चर करना क्योंकि तब यह वास्तव में उदाहरण के संदर्भ को कैप्चर कर रहा है जब तक कि आप स्पष्ट रूप से इसे कॉपी करने के लिए स्पष्ट रूप से चिह्नित नहीं करते हैं।

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

इन परिदृश्यों पर बात की जाती है जहाँ कक्षाएं पसंद की जाती हैं:

  • उदाहरणों की नकल या तुलना करने का कोई मतलब नहीं है (उदाहरण के लिए, विंडो)
  • उदाहरण जीवनकाल बाहरी प्रभावों से जुड़ा होता है (जैसे, TemporaryFile)
  • उदाहरण केवल "सिंक" हैं - केवल बाहरी राज्य के लिए लेखन सामग्री (जैसे CGCONtext)

इसका तात्पर्य यह है कि संरचनाएं डिफ़ॉल्ट होनी चाहिए और कक्षाएं कमबैक होनी चाहिए।

दूसरी ओर, स्विफ्ट प्रोग्रामिंग भाषा प्रलेखन कुछ विरोधाभासी है:

संरचना उदाहरण हमेशा मूल्य से पारित किए जाते हैं, और वर्ग उदाहरण हमेशा संदर्भ द्वारा पारित किए जाते हैं। इसका मतलब है कि वे विभिन्न प्रकार के कार्यों के अनुकूल हैं। जब आप किसी प्रोजेक्ट के लिए आवश्यक डेटा कंस्ट्रक्शंस और कार्यक्षमता पर विचार करते हैं, तो तय करें कि प्रत्येक डेटा कंस्ट्रक्शन को एक वर्ग या एक संरचना के रूप में परिभाषित किया जाना चाहिए या नहीं।

सामान्य दिशानिर्देश के रूप में, एक संरचना बनाने पर विचार करें जब इनमें से एक या अधिक शर्तें लागू हों:

  • संरचना का प्राथमिक उद्देश्य कुछ अपेक्षाकृत सरल डेटा मानों को संक्षिप्त करना है।
  • यह उम्मीद करना उचित है कि जब आप असाइन या उस संरचना के एक उदाहरण के आसपास से गुजरते हैं, तो संदर्भित मानों को कॉपी किया जाएगा।
  • संरचना द्वारा संग्रहीत कोई भी गुण स्वयं मूल्य प्रकार हैं, जिन्हें संदर्भित होने के बजाय कॉपी किए जाने की अपेक्षा की जाएगी।
  • संरचना को किसी अन्य मौजूदा प्रकार से गुण या व्यवहार को इनहेरिट करने की आवश्यकता नहीं है।

संरचनाओं के लिए अच्छे उम्मीदवारों के उदाहरणों में शामिल हैं:

  • एक ज्यामितीय आकार का आकार, शायद एक चौड़ाई संपत्ति और एक ऊंचाई संपत्ति, दोनों प्रकार के डबल को इनकैप्सुलेट कर रहा है।
  • एक श्रृंखला के भीतर पर्वतमाला को संदर्भित करने का एक तरीका, शायद एक प्रारंभ संपत्ति और एक लंबी संपत्ति, दोनों प्रकार के इंट को अलग करना।
  • एक 3 डी समन्वय प्रणाली में एक बिंदु, शायद एक्स, वाई और जेड गुण, टाइप डबल के प्रत्येक encapsulating।

अन्य सभी मामलों में, एक वर्ग को परिभाषित करें और संदर्भ द्वारा प्रबंधित और पारित होने के लिए उस वर्ग के उदाहरण बनाएं। व्यवहार में, इसका मतलब यह है कि अधिकांश कस्टम डेटा निर्माण कक्षाएं होनी चाहिए, न कि संरचनाएं।

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


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

16
@drewag यह जो कह रहा है उसके ठीक विपरीत प्रतीत होता है। यह कह रहा था कि एक वर्ग को डिफ़ॉल्ट होना चाहिए जिसका आप उपयोग करते हैं, न कि एक संरचना जो In practice, this means that most custom data constructs should be classes, not structures.आप मुझे समझा सकते हैं कि, उसे पढ़ने के बाद, आपको लगता है कि अधिकांश डेटा सेट में संरचनाएं होनी चाहिए और कक्षाएं नहीं? उन्होंने नियमों का एक विशिष्ट सेट दिया जब कुछ को एक संरचना होना चाहिए और बहुत अधिक कहा जाना चाहिए "अन्य सभी परिदृश्य एक वर्ग बेहतर है।"
मैट

42
अंतिम पंक्ति को कहना चाहिए, "मेरी व्यक्तिगत सलाह प्रलेखन के विपरीत है:" ... और फिर यह एक महान जवाब है!
दान रोसेनस्टार्क

5
स्विफ्ट 2.2 पुस्तक अभी भी कहती है कि अधिकांश स्थितियों में कक्षाओं का उपयोग करें।
डेविड जेम्स 19

6
कक्षा में संरचना निश्चित रूप से जटिलता को कम करती है। लेकिन जब मेमोरी डिफ़ॉल्ट विकल्प बन जाती है तो मेमोरी के उपयोग पर इसका क्या प्रभाव पड़ता है। जब चीजों को संदर्भ के बजाय हर जगह कॉपी किया जाता है, तो इसे ऐप द्वारा मेमोरी उपयोग में वृद्धि करनी चाहिए। यह नहीं होना चाहिए?
मादनिक

164

चूंकि स्टैक पर स्ट्रक्चर इंस्टेंसेस आवंटित किए जाते हैं, और क्लास इंस्टेंसेस को ढेर पर आवंटित किया जाता है, इसलिए स्ट्रक्चर्स कभी-कभी बहुत तेज हो सकते हैं।

हालाँकि, आपको हमेशा इसे स्वयं मापना चाहिए और अपने अनूठे उपयोग के मामले के आधार पर निर्णय लेना चाहिए।

निम्नलिखित उदाहरण पर विचार करें, जो Intडेटा प्रकार का उपयोग करके रैपिंग की 2 रणनीतियों को प्रदर्शित करता है structऔर class। मैं 10 दोहराया मूल्यों का उपयोग कर रहा हूं, वास्तविक दुनिया को बेहतर ढंग से प्रतिबिंबित करने के लिए हैं, जहां आपके पास कई क्षेत्र हैं।

class Int10Class {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

struct Int10Struct {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

func + (x: Int10Class, y: Int10Class) -> Int10Class {
    return IntClass(x.value + y.value)
}

func + (x: Int10Struct, y: Int10Struct) -> Int10Struct {
    return IntStruct(x.value + y.value)
}

प्रदर्शन का उपयोग करके मापा जाता है

// Measure Int10Class
measure("class (10 fields)") {
    var x = Int10Class(0)
    for _ in 1...10000000 {
        x = x + Int10Class(1)
    }
}

// Measure Int10Struct
measure("struct (10 fields)") {
    var y = Int10Struct(0)
    for _ in 1...10000000 {
        y = y + Int10Struct(1)
    }
}

func measure(name: String, @noescape block: () -> ()) {
    let t0 = CACurrentMediaTime()

    block()

    let dt = CACurrentMediaTime() - t0
    print("\(name) -> \(dt)")
}

कोड https://github.com/knguyen2708/StructVsClassPerformance पर देखे जा सकते हैं

अद्यतन (27 मार्च 2018) :

Swift 4.0, Xcode 9.2 के रूप में, iPhone 6S, iOS 11.2.6 पर रिलीज़ रिलीज़ निर्माण, Swift कम्पाइलर सेटिंग है -O -whole-module-optimization:

  • class संस्करण 2.06 सेकंड लिया
  • struct संस्करण 4.17e-08 सेकंड (50,000,000 बार तेज) लिया

(मैं अब औसत कई रन नहीं बना सकता, क्योंकि संस्करण 5% से कम है)

नोट : अंतर पूरे मॉड्यूल अनुकूलन के बिना बहुत कम नाटकीय है। मुझे खुशी होगी अगर कोई यह बता सके कि झंडा वास्तव में क्या करता है।


अद्यतन (7 मई 2016) :

स्विफ्ट 2.2.1, एक्सकोड 7.3 के रूप में, आईफोन 6 एस, आईओएस 9.3.1 पर रिलीज बिल्ड चल रहा है, जो 5 रन से अधिक है, स्विफ्ट कंपाइलर सेटिंग है -O -whole-module-optimization:

  • class संस्करण 2.159942142s लिया
  • struct संस्करण में 5.83E-08s (37,000,000 गुना तेज) लिया गया

नोट : जैसा कि किसी ने उल्लेख किया है कि वास्तविक दुनिया के परिदृश्यों में, एक संरचना में 1 से अधिक क्षेत्र होने की संभावना होगी, मैंने 1 के बजाय 10 क्षेत्रों के साथ संरचना / कक्षाओं के लिए परीक्षण जोड़े हैं। आश्चर्यजनक रूप से, परिणाम बहुत भिन्न नहीं होते हैं।


मूल परिणाम (1 जून 2014):

(1 क्षेत्र के साथ संरचना / वर्ग पर दौड़े, 10 नहीं)

स्विफ्ट 1.2, Xcode 6.3.2 के रूप में, iPhone 5S, iOS 8.3 पर रिलीज़ बिल्ड चल रहा है, औसतन 5 से अधिक रन

  • class संस्करण 9.788332333s लिया
  • struct संस्करण ने 0.010532942s (900 गुना तेज) लिया

पुराने परिणाम (अज्ञात समय से)

(1 क्षेत्र के साथ संरचना / वर्ग पर दौड़े, 10 नहीं)

मेरी मैकबुक प्रो पर रिलीज़ बिल्ड के साथ:

  • classसंस्करण १.१००८२ सेकंड ले लिया
  • structसंस्करण ०.०२३२४ सेकंड लिया (50 गुना तेजी से)

27
यह सच है, लेकिन ऐसा लगता है कि किसी एकल ऑब्जेक्ट के संदर्भ की नकल करने की तुलना में चारों ओर संरचनाओं का एक गुच्छा नकल करना धीमा होगा। दूसरे शब्दों में, एक एकल पॉइंटर को कॉपी करने की तुलना में तेजी से मेमोरी के बड़े ब्लॉक को कॉपी करना तेजी से होता है।
Tylerc230

14
-1 यह परीक्षण एक अच्छा उदाहरण नहीं है क्योंकि संरचना पर केवल एक ही संस्करण है। ध्यान दें कि यदि आप कई मान और ऑब्जेक्ट या दो जोड़ते हैं, तो स्ट्रक्चर वर्जन क्लास वर्जन के बराबर हो जाता है। आप जितने अधिक वर्जन जोड़ते हैं, स्ट्रक्चर वर्जन उतना ही धीमा होता जाता है।
14

6
@joshrl को आपकी बात मिल गई, लेकिन एक उदाहरण "अच्छा" है या नहीं यह विशिष्ट स्थिति पर निर्भर करता है। यह कोड मेरे स्वयं के ऐप से निकाला गया था, इसलिए यह एक मान्य उपयोग का मामला है, और संरचनाओं का उपयोग करने से मेरे ऐप के प्रदर्शन में व्यापक सुधार हुआ है। यह शायद केवल एक आम उपयोग का मामला नहीं है (ठीक है, सामान्य उपयोग का मामला है, ज्यादातर ऐप्स के लिए, कोई भी इस बात की परवाह नहीं करता है कि डेटा कितनी तेजी से पास किया जा सकता है, क्योंकि अड़चन कहीं और होती है, जैसे नेटवर्क कनेक्शन, वैसे भी, अनुकूलन यह नहीं है कि महत्वपूर्ण जब आपके पास GB या RAM के साथ GHz डिवाइस हैं)।
खान गुयेन

26
जहां तक ​​मैं समझता हूं कि स्विफ्ट में नकल करना राइट टाइम पर होने के लिए अनुकूलित है। जिसका अर्थ है कि कोई भी भौतिक मेमोरी कॉपी तब तक नहीं बनाई जाती है जब तक कि नई कॉपी में बदलाव नहीं किया जाता है।
मटजान

6
यह उत्तर एक बहुत ही तुच्छ उदाहरण है, जो अवास्तविक है और इसलिए कई उदाहरणों के लिए गलत है। एक बेहतर उत्तर होगा "यह निर्भर करता है।"
'19

60

संरचना और वर्गों के बीच समानताएं।

मैंने इसके लिए सरल उदाहरण दिए हैं। https://github.com/objc-swift/swift-classes-vs-structures

और मतभेद

1. वंशानुक्रम।

संरचनाएं तेजी से विरासत में नहीं मिल सकती हैं। अगर तुम चाहते हो

class Vehicle{
}

class Car : Vehicle{
}

एक कक्षा के लिए जाओ।

2. पास

स्विफ्ट संरचनाएं संदर्भ से गुजरती हैं और क्लास इंस्टेंस संदर्भ से गुजरती हैं।

प्रासंगिक अंतर

संरचना स्थिर और चर

उदाहरण (WWDC 2014 में प्रयुक्त)

struct Point{

   var x = 0.0;
   var y = 0.0;

} 

बिंदु नामक एक संरचना को परिभाषित करता है।

var point = Point(x:0.0,y:2.0)

अब अगर मैं एक्स को बदलने की कोशिश करता हूं। इसकी एक वैध अभिव्यक्ति है।

point.x = 5

लेकिन अगर मैंने एक बिंदु को स्थिर के रूप में परिभाषित किया है।

let point = Point(x:0.0,y:2.0)
point.x = 5 //This will give compile time error.

इस मामले में संपूर्ण बिंदु अपरिवर्तनीय स्थिर है।

अगर मैंने इसके बजाय एक क्लास प्वाइंट का उपयोग किया है तो यह एक वैध अभिव्यक्ति है। क्योंकि एक कक्षा में अपरिवर्तनीय स्थिरांक उस वर्ग के संदर्भ में होता है, जिसके उदाहरण चर नहीं होते (जब तक कि उन चर को स्थिरांक के रूप में परिभाषित नहीं किया जाता)



12
उपरोक्त सार यह है कि हम किस प्रकार संरचना के लिए विरासत के स्वादों को प्राप्त कर सकते हैं। आपको सिंटेक्स की तरह दिखाई देगा। ए: बी। यह एक संरचना है जिसे ए एपलमेंट्स प्रोटोकॉल कहा जाता है, जिसे बी। Apple दस्तावेज़ीकरण स्पष्ट रूप से उल्लेख करता है कि संरचना शुद्ध विरासत का समर्थन नहीं करती है और यह नहीं करती है।
मडनिक

2
आदमी है कि तुम्हारा आखिरी पैराग्राफ बहुत अच्छा था। मुझे हमेशा से पता था कि आप स्थिरांक बदल सकते हैं ... लेकिन फिर समय-समय पर मैंने देखा कि जहां आप ऐसा नहीं कर सकते थे मैं चकित था। इस भेद ने इसे दिखाई
हनी

28

यहाँ कुछ अन्य कारणों पर विचार किया गया है:

  1. स्ट्रक्चर्स को एक स्वचालित इनिशियलाइज़र मिलता है जिसे आपको कोड में बनाए रखने की आवश्यकता नहीं है।

    struct MorphProperty {
       var type : MorphPropertyValueType
       var key : String
       var value : AnyObject
    
       enum MorphPropertyValueType {
           case String, Int, Double
       }
     }
    
     var m = MorphProperty(type: .Int, key: "what", value: "blah")

एक कक्षा में इसे पाने के लिए, आपको इनिशियलाइज़र जोड़ना होगा, और इंटेस्टाइज़र को बनाए रखना होगा ...

  1. बुनियादी संग्रह प्रकार जैसे Arrayसंरचनाएं हैं। जितना अधिक आप उन्हें अपने कोड में उपयोग करते हैं, उतना ही आपको संदर्भ के विपरीत मूल्य से गुजरने की आदत होगी। उदाहरण के लिए:

    func removeLast(var array:[String]) {
       array.removeLast()
       println(array) // [one, two]
    }
    
    var someArray = ["one", "two", "three"]
    removeLast(someArray)
    println(someArray) // [one, two, three]
  2. जाहिरा तौर पर अपरिवर्तनीयता बनाम उत्परिवर्तन एक बहुत बड़ा विषय है, लेकिन बहुत सारे स्मार्ट लोग अपरिवर्तनीयता के बारे में सोचते हैं - इस मामले में संरचना - बेहतर है। अपरिवर्तनीय वस्तुएं


4
यह सच है कि आपको स्वचालित आरंभक मिलते हैं। सभी गुण वैकल्पिक होने पर आपको एक खाली इनिशियलाइज़र भी मिलता है। लेकिन, यदि आपके पास एक फ्रेमवर्क में एक संरचना है, तो आपको वास्तव में इनिशियलाइज़र को लिखने की आवश्यकता है यदि आप चाहते हैं कि यह बाहर के internalदायरे में उपलब्ध हो ।
Abizern

2
@Abizern ने पुष्टि की - stackoverflow.com/a/26224873/8047 - और वह आदमी जो कष्टप्रद है।
दान रोसेनस्टार्क

2
@ स्वाइप में सब कुछ के लिए महान कारण हैं, लेकिन हर बार एक जगह पर कुछ सच है और दूसरे में नहीं, डेवलपर को अधिक सामान जानना होगा। मुझे लगता है कि यहाँ मुझे यह कहना चाहिए कि "इस तरह की चुनौतीपूर्ण भाषा में काम करना रोमांचक है!"
डैन रोसेन्स्टार्क

4
क्या मैं यह भी जोड़ सकता हूं कि यह उन संरचनाओं की अपरिहार्यता नहीं है जो उन्हें उपयोगी बनाती हैं (हालांकि यह बहुत अच्छी बात है)। आप स्ट्रक्चर्स को म्यूट कर सकते हैं, लेकिन आपको उन तरीकों को चिह्नित करना होगा, mutatingताकि आप इस बारे में स्पष्ट हो जाएं कि कौन से फ़ंक्शन उनके राज्य को बदलते हैं। लेकिन मूल्य प्रकार के रूप में उनकी प्रकृति महत्वपूर्ण है। यदि आप एक संरचना की घोषणा करते हैं तो आप letउस पर किसी भी म्यूटिंग फ़ंक्शन को कॉल नहीं कर सकते। मूल्य प्रकार के माध्यम से बेहतर प्रोग्रामिंग पर WWDC 15 वीडियो इस पर एक उत्कृष्ट संसाधन है।
अबिज़र्न

1
धन्यवाद @Abizern, मैं वास्तव में आपकी टिप्पणी पढ़ने से पहले कभी नहीं समझ पाया। वस्तुओं के लिए, चलो बनाम var में बहुत अंतर नहीं है, लेकिन संरचना के लिए यह बहुत बड़ा है। इस पर ध्यान दिलाने के लिए धन्यवाद।
दान रोसेनस्टार्क

27

यह मानते हुए कि हम जानते हैं कि संरचना एक मूल्य प्रकार है और कक्षा एक संदर्भ प्रकार है

यदि आप नहीं जानते हैं कि मूल्य प्रकार और संदर्भ प्रकार क्या हैं तो देखें कि संदर्भ बनाम पासिंग मान के बीच अंतर क्या है?

मीकेश की पोस्ट पर आधारित :

... आइए पहले कुछ अतिवादी, स्पष्ट उदाहरणों को देखें। इंटेगर स्पष्ट रूप से कॉपी करने योग्य हैं। उन्हें मूल्य प्रकार होना चाहिए। नेटवर्क सॉकेट को समझदारी से कॉपी नहीं किया जा सकता है। उन्हें संदर्भ प्रकार होना चाहिए। अंक, जैसे कि x, y जोड़े, प्रतिलिपि योग्य हैं। उन्हें मूल्य प्रकार होना चाहिए। एक नियंत्रक जो एक डिस्क का प्रतिनिधित्व करता है उसे समझदारी से कॉपी नहीं किया जा सकता है। यह एक संदर्भ प्रकार होना चाहिए।

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

दृश्य और विंडो नियंत्रक एक समान उदाहरण हैं। हो सकता है कि वे नकल करने योग्य हों, बोधगम्य हों, लेकिन यह लगभग वैसा नहीं है जैसा आप करना चाहते हैं। उन्हें संदर्भ प्रकार होना चाहिए।

मॉडल प्रकारों के बारे में क्या? आपके पास एक उपयोगकर्ता प्रकार हो सकता है जो आपके सिस्टम पर एक उपयोगकर्ता का प्रतिनिधित्व कर रहा है, या एक उपयोगकर्ता द्वारा की गई कार्रवाई का प्रतिनिधित्व करने वाला अपराध प्रकार। ये बहुत नकल करने योग्य हैं, इसलिए उन्हें संभवतः मूल्य प्रकार होना चाहिए। हालाँकि, आप संभवतः प्रोग्राम के अन्य हिस्सों में दृश्यमान होने के लिए अपने प्रोग्राम में एक स्थान पर किए गए उपयोगकर्ता के अपराध के अपडेट चाहते हैं। इससे पता चलता है कि आपके उपयोगकर्ताओं को किसी प्रकार के उपयोगकर्ता नियंत्रक द्वारा प्रबंधित किया जाना चाहिए जो एक संदर्भ प्रकार होगा । जैसे

struct User {}
class UserController {
    var users: [User]

    func add(user: User) { ... }
    func remove(userNamed: String) { ... }
    func ...
}

संग्रह एक दिलचस्प मामला है। इनमें एरेज़ और डिक्शनरी, साथ ही स्ट्रिंग्स जैसी चीजें शामिल हैं। क्या वे कॉपी करने योग्य हैं? जाहिर है। क्या आप आसानी से और अक्सर ऐसा कुछ करना चाहते हैं? यह कम स्पष्ट है।

अधिकांश भाषाएं इसे "नहीं" कहती हैं और अपने संग्रह को संदर्भ प्रकार बनाती हैं। यह Objective-C और Java और Python और JavaScript और लगभग हर दूसरी भाषा में मैं सोच सकता हूँ, में सच है। (एक प्रमुख अपवाद एसटीएल संग्रह प्रकारों के साथ सी ++ है, लेकिन सी ++ भाषा की दुनिया का कहर ढा रही है जो सब कुछ अजीब तरीके से करता है।)

स्विफ्ट ने कहा "हाँ", जिसका अर्थ है कि एरे और डिक्शनरी और स्ट्रिंग जैसे प्रकार कक्षाओं के बजाय संरचना हैं। वे असाइनमेंट पर कॉपी किए जाते हैं, और उन्हें मापदंडों के रूप में पास करने पर। यह एक पूरी तरह से समझदार विकल्प है जब तक कि कॉपी सस्ती है, जिसे स्विफ्ट पूरा करने के लिए बहुत कोशिश करता है। ...

मैं व्यक्तिगत रूप से अपनी कक्षाओं का नाम नहीं देता। मैं आमतौर पर UserController के बजाय मेरा उपयोगकर्ता नाम बताता हूं लेकिन विचार समान है

जब आप किसी फ़ंक्शन की प्रत्येक आवृत्ति को ओवरराइड करना चाहते हैं, तो इसके अलावा कक्षा का उपयोग न करें अर्थात उनमें कोई साझा कार्यक्षमता न हो ।

इसलिए एक वर्ग के कई उपवर्ग होने के बजाय। एक प्रोटोकॉल के अनुरूप कई संरचनाओं का उपयोग करें।


जब आप अपने पुराने और नए मॉडल का डेल्टा / अंतर करना चाहते हैं, तो संरचनाओं के लिए एक और उचित मामला है। संदर्भ प्रकारों के साथ आप बॉक्स से बाहर नहीं कर सकते। मान प्रकार के साथ म्यूटेशन साझा नहीं किए जाते हैं।


1
बिल्कुल उसी तरह का स्पष्टीकरण जिसकी मुझे तलाश थी। अच्छा लिखते हैं :)
androCoder-BD

बहुत उपयोगी नियंत्रक उदाहरण
पूछें

1
@AskP मैंने खुद माइक ईमेल किया और उस अतिरिक्त कोड का कोड मिला :)
Honey

18

कुछ फायदे:

  • स्वचालित रूप से साझा नहीं होने के कारण थ्रेडसेफ़
  • आईए और रिफकाउंट के कारण कम मेमोरी का उपयोग करता है (और वास्तव में स्टैक आमतौर पर आवंटित किया जाता है)
  • विधियां हमेशा सांख्यिकीय रूप से भेजी जाती हैं, इसलिए इनबिल्ट किया जा सकता है (हालांकि @final कक्षाओं के लिए ऐसा कर सकता है)
  • धागे की सुरक्षा के समान कारण के लिए NSArray, NSString, आदि ... के साथ के रूप में "रक्षात्मक प्रति" के लिए कोई ज़रूरत नहीं है के बारे में तर्क करने के लिए आसान

निश्चित नहीं है कि यह इस उत्तर के दायरे से बाहर है, लेकिन क्या आप समझा सकते हैं (या लिंक, मुझे लगता है) "विधियां हमेशा सांख्यिकीय रूप से प्रेषित होती हैं" बिंदु?
दान रोसेनस्टार्क

2
ज़रूर। मैं इसके लिए एक चेतावनी भी संलग्न कर सकता हूं। गतिशील प्रेषण का उद्देश्य एक कार्यान्वयन चुनना है जब आप सामने नहीं जानते हैं कि किसका उपयोग करना है। स्विफ्ट में, जो या तो वंशानुक्रम के कारण हो सकता है (एक उपवर्ग में ओवरराइड हो सकता है), या फ़ंक्शन सामान्य होने के कारण (आप नहीं जानते कि सामान्य पैरामीटर क्या होगा)। संरचनाओं को विरासत में नहीं दिया जा सकता है और पूरे मॉड्यूल-अनुकूलन + जेनेरिक विशेषज्ञता ज्यादातर अज्ञात जेनेरिक को समाप्त करती है, इसलिए विधियों को सीधे कहा जा सकता है बजाय देखने के कि क्या कॉल करना है। विशिष्ट जेनेरिक अभी भी संरचनाओं के लिए गतिशील प्रेषण करते हैं
कैटफ़िश_मन

1
धन्यवाद, शानदार व्याख्या। तो हम एक IDE परिप्रेक्ष्य, या दोनों से अधिक रन गति, या कम अस्पष्टता की उम्मीद कर रहे हैं?
दान रोसेनस्टार्क

1
अधिकतर पूर्व।
कैटफ़िश_मन

यदि आप किसी प्रोटोकॉल के माध्यम से संरचना को संदर्भित करते हैं, तो केवल एक नोट जो विधियाँ वैधानिक रूप से प्रेषण नहीं है।
क्रिस्टिक

12

संरचना वर्ग की तुलना में अधिक तेज है। इसके अलावा, यदि आपको विरासत की आवश्यकता है तो आपको क्लास का उपयोग करना चाहिए। सबसे महत्वपूर्ण बिंदु यह है कि कक्षा संदर्भ प्रकार है जबकि संरचना मूल्य प्रकार है। उदाहरण के लिए,

class Flight {
    var id:Int?
    var description:String?
    var destination:String?
    var airlines:String?
    init(){
        id = 100
        description = "first ever flight of Virgin Airlines"
        destination = "london"
        airlines = "Virgin Airlines"
    } 
}

struct Flight2 {
    var id:Int
    var description:String
    var destination:String
    var airlines:String  
}

अब दोनों का उदाहरण बनाते हैं।

var flightA = Flight()

var flightB = Flight2.init(id: 100, description:"first ever flight of Virgin Airlines", destination:"london" , airlines:"Virgin Airlines" )

अब इन उदाहरणों को आईडी, विवरण, गंतव्य आदि को संशोधित करने वाले दो कार्यों को पास करने देता है।

func modifyFlight(flight:Flight) -> Void {
    flight.id = 200
    flight.description = "second flight of Virgin Airlines"
    flight.destination = "new york"
    flight.airlines = "Virgin Airlines"
}

भी,

func modifyFlight2(flight2: Flight2) -> Void {
    var passedFlight = flight2
    passedFlight.id = 200
    passedFlight.description = "second flight from virgin airlines" 
}

इसलिए,

modifyFlight(flight: flightA)
modifyFlight2(flight2: flightB)

अब अगर हम फ्लाइट की आईडी और विवरण प्रिंट करते हैं, तो हम प्राप्त करते हैं

id = 200
description = "second flight of Virgin Airlines"

यहां, हम देख सकते हैं कि फ्लाइट का आईडी और विवरण बदल दिया गया है, क्योंकि संशोधित विधि में पारित पैरामीटर वास्तव में फ्लाइटा ऑब्जेक्ट (संदर्भ प्रकार) के मेमोरी पते को इंगित करता है।

अब अगर हम FLightB उदाहरण की आईडी और विवरण को प्रिंट करते हैं,

id = 100
description = "first ever flight of Virgin Airlines"

यहां हम देख सकते हैं कि फ़्लाइटबी इंस्टेंस को बदला नहीं गया है क्योंकि मॉडिफाइड 2 विधि में, फ़्लाइट 2 का वास्तविक उदाहरण संदर्भ (वैल्यू टाइप) के बजाय पास किया गया है।


2
आपने FLightB
डेविड सीक

1
तो फिर आप फ्लाइटबी भाई के बारे में क्यों बात कर रहे हैं? Here we can see that the FlightB instance is not changed
डेविड सीक

@ManojKarki, शानदार जवाब। बस यह बताना चाहता था कि आपने दो बार जब आप फ्लाइट ए को घोषित करना चाहते थे, तब फ्लाइटबी घोषित किया।
स्कॉट्टीब्लाड्स

11

Structsहैं value typeऔर Classesहैंreference type

  • मूल्य प्रकार संदर्भ प्रकारों की तुलना में तेज़ होते हैं
  • बहु थ्रेडेड परिवेश में मान प्रकार इंस्टेंस सुरक्षित हैं क्योंकि कई थ्रेड्स दौड़ की स्थिति या गतिरोध के बारे में चिंता किए बिना उदाहरण को उत्परिवर्तित कर सकते हैं
  • मूल्य प्रकार में संदर्भ प्रकार के विपरीत कोई संदर्भ नहीं है; इसलिए मेमोरी लीक नहीं है।

एक valueप्रकार का उपयोग करें जब:

  • आप चाहते हैं कि प्रतियां स्वतंत्र अवस्था में हों, डेटा का उपयोग कई थ्रेड्स में कोड में किया जाएगा

एक referenceप्रकार का उपयोग करें जब:

  • आप साझा, परिवर्तनशील स्थिति बनाना चाहते हैं।

आगे की जानकारी Apple प्रलेखन में भी मिल सकती है

https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html


अतिरिक्त जानकारी

ढेर में स्विफ्ट मान प्रकार रखे जाते हैं। एक प्रक्रिया में, प्रत्येक थ्रेड का अपना स्टैक स्थान होता है, इसलिए कोई अन्य थ्रेड सीधे आपके मान प्रकार तक नहीं पहुंच पाएगा। इसलिए कोई दौड़ की स्थिति, ताले, गतिरोध या किसी भी संबंधित थ्रेड सिंक्रनाइज़ेशन जटिलता नहीं है।

मूल्य प्रकारों को गतिशील मेमोरी आवंटन या संदर्भ गणना की आवश्यकता नहीं होती है, जो दोनों ही महंगे ऑपरेशन हैं। एक ही समय में मूल्य प्रकार के तरीकों को सांख्यिकीय रूप से भेजा जाता है। ये प्रदर्शन के मामले में मूल्य प्रकारों के पक्ष में एक बड़ा लाभ पैदा करते हैं।

यहां एक अनुस्मारक के रूप में स्विफ्ट की एक सूची है

मूल्य प्रकार:

  • struct
  • enum
  • टपल
  • आदिम (इंट, डबल, बूल आदि)
  • संग्रह (ऐरे, स्ट्रिंग, शब्दकोश, सेट)

संदर्भ प्रकार:

  • कक्षा
  • NSObject से कुछ भी आ रहा है
  • समारोह
  • समापन

5

मान प्रकार बनाम संदर्भ प्रकार के परिप्रेक्ष्य से प्रश्न का उत्तर देना, इस Apple ब्लॉग पोस्ट से यह बहुत सरल प्रतीत होगा:

मान प्रकार का उपयोग करें [जैसे संरचना, enum] जब:

  • उदाहरण के साथ डेटा की तुलना == समझ में आता है
  • आप चाहते हैं कि स्वतंत्र राज्य की प्रतियां हों
  • डेटा को कई थ्रेड्स में कोड में उपयोग किया जाएगा

एक संदर्भ प्रकार का उपयोग करें [जैसे वर्ग] जब:

  • उदाहरण के साथ तुलना पहचान === समझ में आता है
  • आप साझा, परिवर्तनशील स्थिति बनाना चाहते हैं

जैसा कि उस लेख में उल्लेख किया गया है, बिना लेखन गुणों वाला एक वर्ग एक संरचना के साथ पहचान के साथ व्यवहार करेगा, (मैं जोड़ूंगा) एक चेतावनी: संरचनाएं थ्रेड-सुरक्षित मॉडल के लिए सबसे अच्छी हैं - आधुनिक ऐप आर्किटेक्चर में एक तेजी से आसन्न आवश्यकता।


3

जिन कक्षाओं में आपको विरासत मिलती है और जिन्हें संदर्भ द्वारा पारित किया जाता है, संरचना में वंशानुक्रम नहीं होता है और मूल्य द्वारा पारित किया जाता है।

स्विफ्ट पर महान डब्ल्यूडब्ल्यूडीसी सत्र हैं, इस विशिष्ट प्रश्न का उत्तर उनमें से एक में बारीकी से दिया गया है। सुनिश्चित करें कि आप उन्हें देखते हैं, क्योंकि यह आपको बहुत तेज़ी से गति करने के लिए मिलेगा, फिर भाषा गाइड या आईबुक।


क्या आप बताए गए कुछ लिंक प्रदान कर सकते हैं? WWDC के कारण से चुनने के लिए काफी कुछ हैं, मैं इस विशिष्ट विषय के बारे में बात करने वाले को देखना चाहता हूं
MMachinegun

मेरे लिए यह यहाँ एक अच्छी शुरुआत है: github.com/raywenderlich/…
MMachinegun

2
वह शायद इस महान सत्र के बारे में बात कर रहा है: स्विफ्ट में प्रोटोकॉल-ओरिएंटेड प्रोग्रामिंग। (लिंक: वीडियो , प्रतिलेख )
zekel

2

मैं यह नहीं कहूंगा कि संरचनाएं कम कार्यक्षमता प्रदान करती हैं।

निश्चित रूप से, म्यूटिंग फ़ंक्शन को छोड़कर स्वयं अपरिवर्तनीय है, लेकिन यह इसके बारे में है।

वंशानुक्रम तब तक ठीक काम करता है जब तक आप अच्छे पुराने विचार से चिपके रहते हैं कि हर वर्ग अमूर्त या अंतिम होना चाहिए।

अमूर्त वर्गों को प्रोटोकॉल के रूप में और अंतिम वर्गों को संरचना के रूप में लागू करें।

स्ट्रक्चर्स के बारे में अच्छी बात यह है कि आप साझा किए गए उत्परिवर्तनीय राज्य बनाए बिना अपने खेतों को उत्परिवर्तित कर सकते हैं क्योंकि लिखने पर प्रतिलिपि इस बात का ध्यान रखती है कि :)

इसीलिए निम्नलिखित उदाहरण में गुण / क्षेत्र सभी परिवर्तनशील हैं, जो मैं जावा या सी # या स्विफ्ट कक्षाओं में नहीं करूंगा ।

उदाहरण में "उदाहरण" नाम के समारोह में नीचे की ओर गंदे और सीधे उपयोग के साथ विरासत की संरचना:

protocol EventVisitor
{
    func visit(event: TimeEvent)
    func visit(event: StatusEvent)
}

protocol Event
{
    var ts: Int64 { get set }

    func accept(visitor: EventVisitor)
}

struct TimeEvent : Event
{
    var ts: Int64
    var time: Int64

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }
}

protocol StatusEventVisitor
{
    func visit(event: StatusLostStatusEvent)
    func visit(event: StatusChangedStatusEvent)
}

protocol StatusEvent : Event
{
    var deviceId: Int64 { get set }

    func accept(visitor: StatusEventVisitor)
}

struct StatusLostStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var reason: String

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

struct StatusChangedStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var newStatus: UInt32
    var oldStatus: UInt32

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

func readEvent(fd: Int) -> Event
{
    return TimeEvent(ts: 123, time: 56789)
}

func example()
{
    class Visitor : EventVisitor
    {
        var status: UInt32 = 3;

        func visit(event: TimeEvent)
        {
            print("A time event: \(event)")
        }

        func visit(event: StatusEvent)
        {
            print("A status event: \(event)")

            if let change = event as? StatusChangedStatusEvent
            {
                status = change.newStatus
            }
        }
    }

    let visitor = Visitor()

    readEvent(1).accept(visitor)

    print("status: \(visitor.status)")
}

2

स्विफ्ट में, एक नया प्रोग्रामिंग पैटर्न प्रोटोकॉल ओरिएंटेड प्रोग्रामिंग के रूप में जाना जाता है।

रचनात्मक पैटर्न:

स्विफ्ट में, स्ट्रक्चर एक वैल्यू टाइप है जो अपने आप क्लोन हो जाता है। इसलिए हमें मुक्त करने के लिए प्रोटोटाइप पैटर्न को लागू करने के लिए आवश्यक व्यवहार मिलता है।

जबकि कक्षाएं संदर्भ प्रकार हैं, जो असाइनमेंट के दौरान स्वचालित रूप से क्लोन नहीं की जाती हैं। प्रोटोटाइप पैटर्न को लागू करने के लिए, कक्षाओं को NSCopyingप्रोटोकॉल को अपनाना होगा ।


उथला प्रतिलिपि केवल संदर्भ को डुप्लिकेट करती है, जो उन वस्तुओं को इंगित करती है जबकि गहरी प्रतिलिपि ऑब्जेक्ट के संदर्भ को दोहराती है।


प्रत्येक संदर्भ प्रकार के लिए गहरी प्रतिलिपि लागू करना एक कठिन कार्य बन गया है। यदि वर्गों में आगे संदर्भ प्रकार शामिल हैं, तो हमें प्रत्येक संदर्भ गुणों के लिए प्रोटोटाइप पैटर्न लागू करना होगा। और फिर हमें वास्तव में प्रोटोकॉल को लागू करके पूरे ऑब्जेक्ट ग्राफ को कॉपी करना होगा ।NSCopying

class Contact{
  var firstName:String
  var lastName:String
  var workAddress:Address // Reference type
}

class Address{
   var street:String
   ...
} 

स्ट्रक्चर्स और एनम का उपयोग करके , हमने अपना कोड सरल बना दिया क्योंकि हमें कॉपी लॉजिक को लागू नहीं करना है।


1

कई कोको एपीआई को NSObject उपवर्गों की आवश्यकता होती है, जो आपको कक्षा का उपयोग करने के लिए मजबूर करता है। लेकिन इसके अलावा, आप एप्पल के स्विफ्ट ब्लॉग से निम्नलिखित मामलों का उपयोग करके यह तय कर सकते हैं कि एक स्ट्रक्चर / एनम वैल्यू टाइप या क्लास रेफरेंस टाइप का उपयोग करना है या नहीं।

https://developer.apple.com/swift/blog/?id=10


0

इन उत्तरों में एक बिंदु पर ध्यान नहीं दिया जा रहा है कि एक वर्ग बनाम एक संरचना को धारण करने वाला एक चर हो सकता है letफिर भी वस्तु के गुणों पर परिवर्तन की अनुमति देता है, जबकि आप एक संरचना के साथ ऐसा नहीं कर सकते।

यह उपयोगी है यदि आप चाहते हैं कि चर कभी किसी अन्य वस्तु की ओर न आए, लेकिन फिर भी वस्तु को संशोधित करने की आवश्यकता होती है, अर्थात कई उदाहरण चर होने की स्थिति में, जिन्हें आप एक के बाद एक अपडेट करना चाहते हैं। यदि यह एक संरचना है, तो आपको ऐसा करने के लिए चर को पूरी तरह से दूसरी वस्तु पर रीसेट करने की अनुमति देनी चाहिए var, क्योंकि स्विफ्ट में एक निरंतर मूल्य प्रकार शून्य उत्परिवर्तन को ठीक से अनुमति देता है, जबकि संदर्भ प्रकार (कक्षाएं) इस तरह का व्यवहार नहीं करते हैं।


0

जैसा कि संरचना मूल्य प्रकार हैं और आप मेमोरी को बहुत आसानी से बना सकते हैं जो स्टैक में संग्रहीत करता है। विनाश आसानी से सुलभ हो सकता है और कार्य के दायरे के बाद स्टैक के शीर्ष से पॉप के माध्यम से स्टैक मेमोरी से आसानी से डील किया जाता है। दूसरी ओर वर्ग एक संदर्भ प्रकार है जो ढेर में संग्रहीत होता है और एक वर्ग वस्तु में किए गए परिवर्तन अन्य वस्तु पर प्रभाव डालते हैं क्योंकि वे कसकर युग्मित होते हैं और संदर्भ प्रकार। किसी संरचना के सभी सदस्य सार्वजनिक होते हैं जबकि एक वर्ग के सभी सदस्य निजी होते हैं ।

संरचना का नुकसान यह है कि यह विरासत में नहीं मिली है।


-7
  • संरचना और वर्ग उपयोगकर्ता परिभाषित डेटा प्रकार हैं

  • डिफ़ॉल्ट रूप से, संरचना एक सार्वजनिक है जबकि वर्ग निजी है

  • क्लास इनकैप्सुलेशन के प्रिंसिपल को लागू करता है

  • एक वर्ग की वस्तुओं को ढेर स्मृति पर बनाया जाता है

  • कक्षा का उपयोग पुन: प्रयोज्य के लिए किया जाता है जबकि संरचना का उपयोग उसी संरचना में डेटा को समूहीकृत करने के लिए किया जाता है

  • संरचना डेटा सदस्यों को सीधे आरंभीकृत नहीं किया जा सकता है, लेकिन उन्हें संरचना के बाहर से सौंपा जा सकता है

  • क्लास डेटा सदस्यों को पैरामीटर कम कंस्ट्रक्टर द्वारा सीधे इनिशियलाइज़ किया जा सकता है और पैरामीटरेड कंस्ट्रक्टर द्वारा सौंपा जा सकता है


2
सबसे खराब जवाब कभी!
जे डो।

कॉपी पेस्ट का जवाब
jawadAli
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.