2009-03-02 21 views
11

सी # में, मेरे पास बेस क्लास उत्पाद और व्युत्पन्न क्लास विजेट है।सी #: मैं व्युत्पन्न वर्ग की स्थैतिक विधि से बेस क्लास की स्थैतिक विधि कैसे कॉल करूं?

उत्पाद में एक स्थिर विधि MyMethod() है।

मैं स्थिर विधि विजेट से MyMethod() को कॉल करना चाहता हूं। MyMethod()।

मैं मूल कीवर्ड का उपयोग नहीं कर सकता, क्योंकि यह केवल उदाहरण विधियों के साथ काम करता है।

मैं स्पष्ट रूप से Product.MyMethod() को कॉल कर सकता हूं, लेकिन अगर मैं बाद में किसी अन्य वर्ग से प्राप्त करने के लिए विजेट बदलता हूं, तो मुझे विधि को संशोधित करना होगा।

क्या सी # के समान कुछ वाक्यविन्यास है जो मुझे बेस क्लास से एक व्युत्पन्न वर्ग की स्थैतिक विधि से स्थिर विधि कॉल करने की अनुमति देता है?

+1

कोई विशेष कारण यह विशेष विधि स्थिर क्यों है? – Rad

उत्तर

16

static विधियां मूल रूप से ऑब्जेक्ट उन्मुख अवधारणाओं से फ़ॉलबैक करने का एक तरीका हैं। नतीजतन, वे विरासत पदानुक्रमों में बहुत लचीला नहीं हैं और ऐसी चीज सीधे करना संभव नहीं है।

निकटतम चीज़ जो मैं सोच सकता हूं वह using निर्देश है।

using mybaseclass = Namespace.BaseClass; 

class MyClass : mybaseclass { 

    static void MyMethod() { mybaseclass.BaseStaticMethod(); } 

} 
+4

> स्थैतिक विधियां मूल रूप से फ़ॉलबैक के लिए एक विधि हैं ... यह सच क्यों है? मेरी कक्षा के लिए कोड में, उदाहरण डेटा पर निर्भर विधियां उदाहरण विधियां हैं। वे विधियां जो उदाहरण डेटा पर भरोसा नहीं करती हैं, लेकिन केवल पैरामीटर (यदि कोई हैं) पर निर्भर हैं, वे स्थिर तरीके हैं। मुझे यह भेद उपयोगी लगता है। – MindModel

+0

एक विधि जो * ऑब्जेक्ट * इंस्टेंस पर भरोसा नहीं करती है वह ऑब्जेक्ट्स (वर्चुअल विधि प्रेषण, ...) के लिए परिभाषित अधिकांश नियमों द्वारा नहीं खेलती है। –

+0

दिमागी मॉडल, जबकि इसके लिए कुछ परिदृश्य हैं, यदि आप विरासत की आवश्यकता शुरू करते हैं या [किसी भी अन्य प्रतिबंध बनाम गैर स्थैतिक तरीकों को सम्मिलित करते हैं] यह एक लक्षण है कि कुछ और हो सकता है ... शायद कक्षा में बहुत अधिक जिम्मेदारियां हैं – eglasius

0

खाता है कि एक स्थिर विधि उदाहरण डेटा में रिले shoudn't में होने ... आप एक स्थिर "MyMethod" है कि एक पैरामीटर या ऐसा ही कुछ के आधार पर अलग-अलग तरह व्यवहार करता है होना चाहिए।

याद रखें कि एक वर्ग में परिभाषित स्थैतिक विधि आपके कोड को ऑर्डर करने का एक तरीका है ... लेकिन यह वही है यदि वह विधि कहीं और स्थित है ... क्योंकि यह उस ऑब्जेक्ट पर रिले नहीं है जहां यह है रखा हे।

संपादित करें: मुझे लगता है कि आपका सबसे अच्छा choise उत्पाद का उपयोग करना है। MyMethod स्पष्ट रूप से ... यदि आपको लगता है ... यह संभव नहीं होना चाहिए कि आपका विजेट अपना बेस क्लोज़ बदलता है ... और उसमें भी मामला यह कोड में मामूली परिवर्तन है।

+0

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

+0

सच है। आप स्थैतिक चर (एक वर्ग प्रति) और आवृत्ति चर (एक प्रति उदाहरण) के बीच का अंतर जानते हैं। यह भेद क्यों उपयोगी नहीं है? यह ओओ डिजाइन खराब क्यों है? – MindModel

+0

खैर, मुझे यह कहना चाहिए था कि आपको "वैरिएबल" उदाहरण डेटा में रिले नहीं करना चाहिए ... बेशक आप "कर सकते हैं"। :) – Romias

1

स्टेटिक विधियां पॉलिमॉर्फिक नहीं हैं, इसलिए आप जो करना चाहते हैं वह असंभव है।

स्थिर तरीकों का इलाज करने के लिए रास्ता खोजने का प्रयास करना क्योंकि पॉलिमॉर्फिक संभव है लेकिन खतरनाक है, क्योंकि भाषा स्वयं इसका समर्थन नहीं करती है।

कुछ सुझाव:

  • प्रतिबिंब
  • (जैसे Mehrdad's example के रूप में)
4

यह किया जा सकता है, लेकिन मैं इसकी सलाह नहीं देते आधार वर्ग अलियासिंग।

public class Parent1 
{ 
    public static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public new static void Foo() 
    { 
     Type parent = typeof(Child).BaseType; 
     MethodInfo[] methods = parent.GetMethods(); 
     MethodInfo foo = methods.First(m => m.Name == "Foo"); 
     foo.Invoke(null, null); 
    } 
} 
+4

पर्याप्त मेला। इस मामले में, समाधान समस्या से भी बदतर है। धन्यवाद। – MindModel

+0

बिल्कुल। स्ट्रिंग का उपयोग करने के दस वर्ण – marcumka

+2

nstead आप MethodBase.GetCurrentMethod() का उपयोग कर सकते हैं। नाम –

0

स्टेटिक विधियां "कक्षा-स्तर" विधियां हैं। वे विधियों का इरादा रखते हैं जो एक विशिष्ट वर्ग के सभी उदाहरणों पर लागू होते हैं। इस प्रकार, इस विधि की विरासत को समझ में नहीं आता है क्योंकि यह कक्षा के उदाहरणों पर लागू होने के अर्थ को बदल देगा। उदाहरण के लिए, यदि आप उत्पादों के संग्रह (कुछ विजेट, कुछ नहीं) के माध्यम से लूपिंग कर रहे थे और प्रत्येक उत्पाद पर MyMethod कहा जाता है तो उस विधि को क्लास के उदाहरण द्वारा निर्धारित किया जाएगा। यह स्थैतिक तरीकों के उद्देश्य का उल्लंघन करता है।

आप शायद कुछ तो आप बस बिल्कुल स्थिर तरीकों का उपयोग कर नहीं, क्योंकि आपके उदाहरण में ऐसा प्रतीत नहीं होता MyMethod उत्पाद के सभी उदाहरणों पर लागू होता है की तरह से अधिक सफाई से चाहते हैं की तरह कर सकते हैं। हालांकि, आप 'IMyMethod' जैसे इंटरफ़ेस क्लास का उपयोग कर वर्णन कर रहे एक ही प्रभाव को प्राप्त कर सकते हैं। यह दृष्टिकोण अभी भी स्थिर विधि का उपयोग नहीं कर रहा है। मुझे लगता है कि मुझे एक स्थिर विधि की आवश्यकता नहीं दिख रही है। आप शुरू करने के लिए एक स्थिर विधि का उपयोग क्यों करना चाहते हैं?

4

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

var type = assy.GetType("MyNamespace.MyType"); 
MethodInfo mi = type.GetMethod("MyStaticMethod", 
    BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); 
mi.Invoke(null, null); 

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

-1

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

public class BaseThings 
{ 
    protected static void AssertPermissions() 
    { 
     //something 
    } 
} 

public class Person:BaseThings 
{ 
    public static void ValidatePerson(Person person) 
    { 
     //just call the base static method as if it were in this class. 
     AssertPermissions();    
    } 
} 
+0

हारून, ओपी के आधार और व्युत्पन्न कक्षाओं के लिए एक ही विधि का नाम है। इस तथ्य के साथ कि वह स्पष्ट रूप से 'Base.StaticMethod' निर्दिष्ट नहीं करना चाहती, ये दोनों समस्या का क्रूक्स हैं। – nawfal

2

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

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

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

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

2

यह किया जा सकता है:

public class Parent1 
{ 
    protected static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public static void Foo() 
    { 
     return Parent1.Foo(); 
    } 
} 

इकाई परीक्षण संरक्षित स्थिर तरीकों (उदाहरण के लिए) के लिए उपयोगी हो सकता है।

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