2013-05-19 4 views
30

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

class Warrior { 
    unsigned int m_health; 
    unsigned int m_armor; 
}; 

अब किसी एक विशेष हमले कि 5 सेकंड के लिए अपने कवच कम कर देता है के साथ अपने योद्धा पर हमला करता है:


विशेषताओं health और armor के साथ एक कक्षा Warrior कल्पना कीजिए। सेटर के हैं का उपयोग करते हुए इसे इस तरह हो:

void Attacker::attack(Warrior *target) 
{ 
    target->setHealth(target->getHealth() - m_damage); 
    target->setArmor(target->getArmor() - 20); 
    // wait 5 seconds 
    target->setArmor(target->getArmor() + 20); 
} 

और साथ कहता हूं, यह इस (मुझे सही कर अगर मैं गलत हूँ) की तरह लग रहे हैं सिद्धांत मत पूछो:

void Attacker::attack(Warrior *target) 
{ 
    target->hurt(m_damage); 
    target->reduceArmor(20); 
    // wait 5 seconds 
    target->increaseArmor(20); 
} 

अब दूसरा स्पष्ट रूप से बेहतर दिखता है, लेकिन मुझे इसका वास्तविक लाभ नहीं मिल रहा है। आपको अभी भी वही मात्रा (increase/decrease बनाम set/get) की आवश्यकता है और आप पूछने का लाभ खो देते हैं कि आपको कभी पूछने की आवश्यकता है या नहीं। उदाहरण के लिए, आप योद्धाओं के स्वास्थ्य को 100 कैसे सेट करेंगे? आप कैसे पता लगाते हैं कि आपको heal या hurt का उपयोग करना चाहिए, और आपको कितना स्वास्थ्य ठीक करने या चोट पहुंचाने की आवश्यकता है?

इसके अलावा, मैं दुनिया के कुछ सर्वश्रेष्ठ प्रोग्रामर द्वारा सेटर्स और गेटर्स का उपयोग किया जा रहा हूं। अधिकांश एपीआई इसका इस्तेमाल, और यह एसटीडी lib में हर समय इस्तेमाल किया जा रहा:

for (i = 0; i < vector.size(); i++) { 
    my_func(i); 
} 
// vs. 
vector.execForElements(my_func); 

और यहाँ लोगों का मानना ​​है है कि क्या मुझे एक लेख के बारे में कह जोड़ने, नहीं पूछ, या करने के लिए तय करने के लिए करता है, तो मेरे पास है 9 0% बड़ी कंपनियों (सेब, माइक्रोसॉफ्ट, एंड्रॉइड, अधिकांश खेलों इत्यादि) पर विश्वास करें जिन्होंने सफलतापूर्वक बहुत पैसा और कामकाजी कार्यक्रम किए हैं, यह समझना मेरे लिए मुश्किल है कि क्यों बताएंगे, टी पूछें एक अच्छा सिद्धांत हो।

मुझे इसका उपयोग क्यों करना चाहिए (मुझे चाहिए?) जब सब कुछ गेटर्स और सेटर्स के साथ आसान लगता है?

+0

एक एकल एचपी या एकल कवच का उपयोग करने के बजाय, आप एक एचपी_रेक्शन सूची और armor_reduction सूची का उपयोग कर सकते हैं ताकि जब कई दुश्मन एक ही पीड़ित हो जाएं, तो वे स्वास्थ्य और कवच के लिए समान चर तक पहुंचने वाले एकाधिक धागे की वजह से स्वास्थ्य और कवच को नहीं देखते हैं । धागे में 5 सेकंड इंतजार करना है ना? आप कैसे सुनिश्चित कर सकते हैं कि यह बिल्कुल 5 सेकंड तक प्रतीक्षा करता है? आपको कार्य शेड्यूलर भी चाहिए। –

+7

@huseyintugrulbuyukisik धन्यवाद, लेकिन मैं यहां एक कामकाजी गेम कोड करने की कोशिश नहीं कर रहा हूं ._। यह सिर्फ एक साधारण उदाहरण था –

+0

फिर आप सबसे सरल असाइनिंग ऑपरेशंस के साथ जा सकते हैं। Warrior.HP- = 5; –

उत्तर

32

आपको अभी भी वही मात्रा (वृद्धि/कमी बनाम सेट/प्राप्त) की आवश्यकता है और आप पूछने का लाभ खो देते हैं कि आपको कभी पूछने की आवश्यकता है या नहीं।

आपको यह गलत लगता है। बिंदु getVariable और setVariable को एक सार्थक ऑपरेशन के साथ प्रतिस्थापित करना है: उदाहरण के लिए inflictDamagegetVariableincreaseVariable के साथ प्रतिस्थापित करने से आपको गेटटर और सेटर के लिए अलग-अलग अस्पष्ट नाम मिलते हैं।

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

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

खेल को जटिल करें और आग हथियार जोड़ें, तो आपके पास inflictFireDamage हो सकता है (या inflictDamage फ़ंक्शन के लिए एक अलग तर्क के रूप में अग्नि क्षति को पारित करें)। Warrior यह पता लगा सकता है कि क्या वह अग्नि प्रतिरोध वर्तनी से प्रभावित है या नहीं, कार्यक्रम में अन्य सभी ऑब्जेक्ट्स रखने के बजाए आग की क्षति को नजरअंदाज कर दें, यह पता लगाने की कोशिश करें कि उनकी कार्रवाई दूसरों को कैसे प्रभावित करेगी।

+3

यह एकमात्र पूरक उत्तर था जो वास्तव में कहने के बजाय * बताओ, * पूछो * के लाभों को समझाया गया है, "डुह, यह आपको बेहतर encapsulation देता है"। आप पूरी तरह स्वीकार्य हैं, जवाब के लिए धन्यवाद! :) –

2

ठीक है, अगर ऐसा है, तो गेटर्स और सेटर्स के साथ परेशान क्यों हो? आप सिर्फ सार्वजनिक क्षेत्र कर सकते हैं।

void Attacker::attack(Warrior *target) 
{ 
    target->health -= m_damage; 
    target->armor -= 20; 
    // wait 5 seconds 
    target->armor += 20; 
} 

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

लेख का हवाला देते हुए:

यहां सबसे बड़ा खतरा है कि एक वस्तु से डेटा के लिए पूछ करके, आप केवल डेटा हो रही है। आपको ऑब्जेक्ट नहीं मिल रहा है-बड़े अर्थ में नहीं। भले ही आपको किसी क्वेरी से प्राप्त वस्तु एक वस्तु संरचनात्मक रूप से (उदा।, एक स्ट्रिंग) है, यह अब ऑब्जेक्ट को निष्क्रिय रूप से नहीं है। अब इसके मालिक ऑब्जेक्ट के साथ कोई संबंध नहीं है। सिर्फ इसलिए कि आपको एक स्ट्रिंग मिली है जिसका सामग्री "लाल" थी, आप स्ट्रिंग से इसका क्या मतलब नहीं पूछ सकते हैं। क्या यह मालिकों का अंतिम नाम है? कार का रंग? टैकोमीटर की वर्तमान स्थिति? एक वस्तु इन चीजों को जानता है, डेटा नहीं करता है।

यहां आलेख बताता है कि "बताओ, मत पूछो" यहां बेहतर है क्योंकि आप ऐसी चीजें नहीं कर सकते हैं जो कोई समझ नहीं लेते हैं।

target->setHealth(target->getArmor() - m_damage); 

यह समझ में नहीं आता है, क्योंकि कवच के स्वास्थ्य के संबंध में कुछ भी नहीं है।

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

std::for_each(begin(v), end(v), my_func); 
std::copy(begin(v), end(v), begin(u)); 
+0

मैं इसे रखने के लिए 'स्वास्थ्य' को बदलना पसंद करूंगा> = 0 मुझे इसके बारे में चिंता करने के बिना व्यक्तिगत रूप से। – chris

+0

और पूरी तरह से encapsulation भूल जाओ। समझ में आता है ... नहीं। तब आप इनवेरिएंट को कैसे बनाए रखते हैं? – syam

+0

@syam इससे कोई फर्क नहीं पड़ता। यह सिर्फ एक कट्टरपंथी सवाल था। (आप यह कैसे करेंगे? आप 'स्वास्थ्य' के प्रकार को बदल सकते हैं जो int के समान है, फिर भी कुछ अलग करता है। हालांकि बुरा विचार) – milleniumbug

1

एक कारण जो दिमाग में आता है वह यह तय करने की क्षमता है कि आप कहां नियंत्रण चाहते हैं।

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

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

+0

गैर-धोखाधड़ी हिटपॉइंट मान भी हमले समारोह में संरक्षित किए जा सकते हैं। –

+0

आप इनमें से अधिकतर सेटर में भी कर सकते हैं, है ना? –

0

मेरे दृष्टिकोण पर, दोनों कोड एक ही काम करते हैं। अंतर प्रत्येक की व्यक्तित्व में है। पहला वाला (सेटर्स एनाड गेटर्स) दूसरे (बताएं, डॉन ' से पूछें) से अधिक अभिव्यक्तिपूर्ण हो सकता है।

यह सच है कि, जब आप पूछते हैं, तो आप निर्णय लेने जा रहे हैं। लेकिन यह कई बार में नहीं होता है। कभी-कभी आप ऑब्जेक्ट के कुछ मूल्य को जानना या सेट करना चाहते हैं, और के साथ यह संभव नहीं है, से पूछें नहीं।

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

वास्तव में, getters और setters की तस है, लेकिन यह बताई करने के विचार को देखने के लिए, मत पूछो एक साथ इसके साथ आम है। दूसरे शब्दों में, कुछ एपीआई में गेटर्स और सेटर्स होते हैं और के तरीके भी बताते हैं, विचार न पूछें।

संबंधित मुद्दे