हाल ही में मोजो में विशेषताएं पेश की गईं, इसलिए मैंने सोचा कि मैं उन्हें आज़माऊंगा। वर्तमान में, अंतर्निहित लक्षणों में , , , , , , और शामिल हैं (ऐसा लगता है कि इन नामकरण परंपराओं में "-able" प्रत्यय एक चीज़ है!)। लक्षण संरचनाओं पर काम करते हैं। किसी विशेषता को लागू करने के लिए, आप बस संरचना में एक विधि जोड़ते हैं जो विशेषता से मेल खाती है; फिर विशेषता नाम को पैरामीटर के रूप में पास करें: CollectionElement Copyable Destructable Intable Movable Sized Stringable @value struct Duck(Quackable): fn quack(self): print("Quack!") मोजो में डेकोरेटर , और जैसी जीवनचक्र विधियों को संरचना में सम्मिलित करता है, जिससे हमारा जीवन थोड़ा सरल हो जाता है क्योंकि हमें उन्हें स्वयं जोड़ने की आवश्यकता नहीं होती है। @value __init__() __copyinit__() __moveinit__() मोजो में लक्षण अभी तक विधियों के लिए डिफ़ॉल्ट कार्यान्वयन का समर्थन नहीं करते हैं, इसलिए, उपरोक्त विधि के मुख्य भाग में आप भी उपयोग कर सकते हैं, जिसका प्रभाव Python जैसा ही होगा। Quackable ... pass मोजो ट्रेट्स बनाम गो इंटरफेसेस अलग-अलग नाम के बावजूद, मोजो में लक्षणों के लिए बुनियादी दृष्टिकोण मुझे गो इंटरफेस की याद दिलाता है। गो में, आप एक संरचना को परिभाषित करेंगे और इस तरह एक इंटरफ़ेस लागू करेंगे: Duck Quackable type Quackable interface { quack() } और एक ऐसी संरचना बनाने के लिए जो इस इंटरफ़ेस को संतुष्ट करती हो: type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") } इसकी तुलना मोजो कार्यान्वयन से करें: trait Quackable: fn quack(self): ... @value struct Duck(Quackable): fn quack(self): print("Quack!") मुझे लगता है कि मोजो संस्करण और भी अधिक संक्षिप्त है, जो संरचना प्रकार के अंदर विधि परिभाषा को समाहित करता है। संरचनाओं पर काम करने के अलावा, मोजो में लक्षणों के लिए गो की तरह ही कीवर्ड की आवश्यकता नहीं होती है। Duck quack() implements दिलचस्प बात यह है कि मोजो डॉक्स में यह बात कही गई है कि डिफ़ॉल्ट कार्यान्वयन की अनुमति नहीं है, जिसका अर्थ है कि भविष्य में उन्हें अनुमति दी जा सकती है। इसका मतलब यह है कि मोजो गो से अलग दृष्टिकोण अपना सकता है, जो इंटरफ़ेस को संरचनाओं पर ध्यान केंद्रित करता है, न कि इसे । अभी संतुष्ट करने वाली लागू करने पर गो में डिफ़ॉल्ट विधि कार्यान्वयन की आवश्यकता नहीं है, और एक समान प्रभाव एम्बेडिंग के साथ प्राप्त किया जाता है, क्योंकि इंटरफ़ेस/विशेषता कार्यान्वयन केवल एक अवधारणा है जो गो में मौजूद नहीं है। मोजो में चीज़ें भिन्न हो सकती हैं। मोजो गुणों का उपयोग कैसे करें लक्षण और इंटरफ़ेस का महत्व कोड को पुन: प्रयोज्य बनाना है। उदाहरण के लिए, मोजो में, आप ऐसे फ़ंक्शन लिख सकते हैं जो विशेषता प्रकारों को स्वीकार करते हैं... fn make_it_quack[T: Quackable](could_be_duck: T): could_be_duck.quack() और फिर अलग-अलग संरचनाएं पास करें जो इनपुट के समान गुण को लागू करती हैं - सब कुछ बस काम करेगा! उदाहरण के लिए, यहां एक संरचना है जो लागू करती है: Goose Quackable @value struct Goose(Quackable): fn quack(self): print("Honk!") और यहां, और दोनों पर कॉल करने के लिए (याद रखें, आपको अपने प्रोग्राम में प्रवेश बिंदु के रूप में मोजो में फ़ंक्शन की आवश्यकता है): Goose Duck make_it_quack main def main(): make_it_quack(Duck()) make_it_quack(Goose()) इसका आउटपुट होगा Quack! Honk! लक्षण त्रुटियाँ यदि मैंने कुछ ऐसा पारित करने का प्रयास किया है जो फ़ंक्शन में विशेषता को लागू नहीं करता है, मान लें कि , प्रोग्राम संकलित नहीं होगा: make_it_quack Quackable StealthCow @value struct StealthCow(): pass make_it_quack(StealthCow()) नीचे दिया गया त्रुटि संदेश अधिक वर्णनात्मक हो सकता था; शायद मोजो टीम इसमें सुधार करेगी? error: invalid call to 'make_it_quack': callee expects 1 input parameter, but 0 were specified यदि मैं से विधि हटा दूं तो भी ऐसा ही होगा; यहाँ, हमें एक अच्छी, वर्णनात्मक त्रुटि मिलती है: Goose quack struct 'Goose' does not implement all requirements for 'Quackable' required function 'quack' is not implemented शुद्ध पायथन दृष्टिकोण की तुलना में इस प्रकार की स्थैतिक प्रकार की जाँच का लाभ यह है कि हम त्रुटियों को आसानी से पकड़ सकते हैं और किसी भी गलती को उत्पादन में भेजने से बच सकते हैं क्योंकि कोड आसानी से संकलित नहीं होगा। विरासत मोजो में लक्षण पहले से ही वंशानुक्रम का समर्थन करते हैं, इसलिए हमारा `क्वैकएबल` गुण `श्रव्य` गुण का विस्तार इस प्रकार कर सकता है: trait Audible: fn make_sound(self): ... trait Quackable(Audible): fn quack(self): ... इसका मतलब यह है कि संरचना को विशेषता के अनुरूप होने के लिए और दोनों को लागू करना होगा। Duck Quackable quack make_sound यह गो में "इंटरफ़ेस एम्बेडिंग" की अवधारणा के समान है, जहां एक नया इंटरफ़ेस बनाने के लिए जो अन्य इंटरफ़ेस से प्राप्त होता है, आपको इस तरह से मूल इंटरफ़ेस एम्बेड करना होगा: type Quackable interface { Audible // includes methods of Audible in Quackable's method set } स्थैतिक तरीके लक्षण स्थिर तरीकों को भी स्वीकार करते हैं जो किसी संरचना का उदाहरण बनाए बिना काम करते हैं: trait Swims: @staticmethod fn swim(): ... @value struct Duck(Quackable, Swims): fn quack(self): print("Quack!") @staticmethod fn swim(): print("Swimming") fn make_it_swim[T: Swims](): T.swim() आप इस प्रकार एक स्थिर विधि को कॉल करते हैं: def main(): make_it_quack(Duck()) make_it_quack(Goose()) Duck.swim() जो आउटपुट देगा: Quack! Honk! Swimming ध्यान दें कि अंतिम विधि कॉल में, डक इंस्टेंस नहीं बनाया गया है। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग से कुछ हद तक हटकर, पायथन में स्थिर विधियाँ इस प्रकार काम करती हैं। मोजो इस पायथन कार्यक्षमता पर आधारित है। गो इंटरफेस की तुलना में मोजो लक्षणों की सीमाएं दिलचस्प बात यह है कि एक खाली जो किसी भी प्रकार को पास करने की अनुमति देती है और गो जेनेरिक्स पेश किए जाने से पहले गो समुदाय के साथ लोकप्रिय थी, मोजो-टाइप किए गए फ़ंक्शन के साथ काम नहीं करेगी। interface{} fn आपकी संरचना को या जैसी जीवनचक्र विधियों में से कम से कम एक को लागू करना होगा, जो इस मामले में, इसे या के अनुरूप बनाएगा, जिसका उपयोग उन कार्यों के साथ किया जाएगा जो विशेषता प्रकारों को स्वीकार करते हैं। __len__ __str__ Sized Stringable यह वास्तव में कोई वास्तविक सीमा नहीं है और मोजो में बहुत मायने रखता है, क्योंकि, मोजो के साथ, यदि आपको गतिशील टाइपिंग की आवश्यकता है, तो आप अधिक लचीले फ़ंक्शन पर वापस आ सकते हैं, और फिर अज्ञात के साथ काम करने के लिए सामान्य पायथन जादू लागू कर सकते हैं प्रकार. def अधिक सख्त मोजो फ़ंक्शन जैसे प्रकारों का उपयोग करके सामान्य संरचनाओं पर भी काम करते हैं; उसके बारे में और अधिक पढ़ें । fn DynamicVector यहां एक और सीमा जो मैं देखता हूं वह लक्षणों के बजाय संरचनाओं और उनकी विधियों से संबंधित है और स्वच्छ वास्तुकला को लागू करने/कोड को विभिन्न भागों में अलग करने में एक संभावित बाधा है। गो बनाम मोजो संरचना विधि परिभाषा के साथ पिछले उदाहरणों में से एक पर विचार करें: type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") } @value struct Duck(Quackable): fn quack(self): print("Quack!") मोजो उदाहरण, अधिक पायथन-जैसे वाक्यविन्यास का पालन करते हुए, विधि परिभाषा को सीधे संरचना के अंदर रखता है, जबकि गो संस्करण इसे संरचना से अलग करने की अनुमति देता है। इस संस्करण में, यदि मेरे पास कई प्रकारों और विधियों के साथ एक बहुत लंबी संरचना है, तो इसे पढ़ना कुछ हद तक कठिन होगा। हालाँकि यह कोई गंभीर अंतर नहीं है, बस जागरूक होने की बात है। भाषा के शुरुआती दौर में होने के बावजूद मोजो के लक्षण पहले से ही काफी उपयोगी हैं। जबकि गो दर्शन पूरी तरह से सरलता के बारे में है और सुविधाओं को न्यूनतम रखने की कोशिश करता है, यह संभावना है कि हम भविष्य में मोजो विशेषताओं में और अधिक कार्यक्षमता जोड़ेंगे, जिससे वे और भी अधिक शक्तिशाली बन जाएंगे और कई अलग-अलग उपयोग के मामलों को सक्षम कर पाएंगे।