मैं सी # में अमूर्त स्थैतिक तरीकों क्यों नहीं कर सकता?

मैं हाल ही में प्रदाताओं के साथ काम कर रहा हूं, और मैं आया एक दिलचस्प परिस्थिति में जहां मैं एक अमूर्त वर्ग चाहता था जिसमें एक अमूर्त स्थिर विधि थी। मैंने विषय पर कुछ पोस्ट पढ़ी हैं, और यह समझ में आया है, लेकिन क्या कोई स्पष्ट स्पष्ट स्पष्टीकरण है?

0
जोड़ा संपादित
विचारों: 1
कृपया भविष्य में सुधार की अनुमति देने के लिए इन्हें खोलें।
जोड़ा लेखक Mark Biek, स्रोत
बेस क्लास में, विधि अनसुलझा है, और आप इसका उपयोग नहीं कर सकते हैं। आपको या तो व्युत्पन्न प्रकार या ऑब्जेक्ट की आवश्यकता है (जो बदले में व्युत्पन्न प्रकार होगा)। आप baseClassObject.Method() या DerivedClass.Method() को कॉल करने में सक्षम होना चाहिए। आप BaseClass.Method() को कॉल नहीं कर सकते क्योंकि यह आपको प्रकार नहीं देता है।
जोड़ा लेखक William Jockusch, स्रोत
मुझे लगता है कि सवाल इस तथ्य पर हो रहा है कि सी # को इस तरह की स्थिति के लिए एक और कीवर्ड की जरूरत है। आप एक विधि चाहते हैं जिसका वापसी मूल्य केवल उस प्रकार पर निर्भर करता है जिस पर इसे कहा जाता है। यदि यह कहा गया है कि आप अज्ञात हैं तो आप इसे "स्थैतिक" नहीं कह सकते हैं। लेकिन एक बार जब प्रकार ज्ञात हो जाता है, तो यह स्थिर हो जाएगा। "अनसुलझा स्थिर" विचार है - यह अभी तक स्थिर नहीं है, लेकिन एक बार जब हम प्राप्त करने वाले प्रकार को जानते हैं, तो यह होगा। यह एक पूरी तरह से अच्छी अवधारणा है, यही कारण है कि प्रोग्रामर इसके लिए पूछते रहते हैं। लेकिन डिजाइनरों ने भाषा के बारे में सोचा जिस तरह से यह क
जोड़ा लेखक William Jockusch, स्रोत
जोड़ा लेखक peterh, स्रोत
@WilliamJockusch प्रकार प्राप्त करने का मतलब क्या है? यदि मैं BaseClass.StaticMethod() को कॉल करता हूं तो बेसक्लास एकमात्र प्रकार है जिसका उपयोग निर्णय लेने के लिए किया जा सकता है। लेकिन इस स्तर पर यह सार है इसलिए विधि को हल नहीं किया जा सकता है। यदि आप इसके बजाय DerivedClass.StaticMethod को अच्छी तरह से कॉल करते हैं तो बेस क्लास अप्रासंगिक है।
जोड़ा लेखक Martin Capodici, स्रोत
साइड नोट के रूप में, TextWriter.Null और StreamWriter.Null ने इस विषय के आसपास एक समान प्रयास दिखाया।
जोड़ा लेखक Ken Kin, स्रोत

7 उत्तर

पिछले स्पष्टीकरण में जोड़ने के लिए, स्थिर विधि कॉल संकलन-समय पर एक विशिष्ट विधि से बंधी हुई हैं, जो कि पॉलिमॉर्फिक व्यवहार को नियंत्रित करती है।

0
जोड़ा
तो सीएलआर पर पॉलिमॉर्फिज्म वास्तव में आपको कैसे लगता है? आपकी व्याख्या ने वर्चुअल विधि प्रेषण से इंकार कर दिया।
जोड़ा लेखक Rytmis, स्रोत
माफ़ी, मेरा मतलब अपमान नहीं था (हालांकि मैं थोड़ा सा जवाब देने के लिए स्वीकार करता हूं ;-)। मेरे प्रश्न का मुद्दा यह था कि, यदि आपको ये कक्षाएं मिली हैं: कक्षा बेस {सार्वजनिक वर्चुअल शून्य विधि (); } वर्ग व्युत्पन्न: आधार {सार्वजनिक ओवरराइड शून्य विधि (); } और इस प्रकार लिखें: आधार उदाहरण = नया व्युत्पन्न (); instance.Method (); कॉल साइट पर संकलन-समय की प्रकार की जानकारी यह है कि वास्तविक आधार एक व्युत्पन्न होने पर हमें आधार का एक उदाहरण मिला है। तो संकलक कॉल करने के लिए सही विधि को हल नहीं कर सकता है। इसके बजाए यह एक "कॉलवर्ट" आईएल निर्देश उत्सर्जित करता है जो रनटाइम को प्रेषित करने के लिए कह
जोड़ा लेखक Rytmis, स्रोत
... जबकि स्थैतिक तरीकों के लिए, वर्चुअल प्रेषण करने के लिए कोई उदाहरण नहीं है, इसलिए यह हमेशा एक "कॉल" निर्देश उत्सर्जित करता है। और अब जब मैंने अपने जवाब पर विस्तार किया, तो मुझे एहसास हुआ कि यह एक क्रोधित जवाब क्या था। ;-)
जोड़ा लेखक Rytmis, स्रोत
धन्यवाद आदमी, जानकारीपूर्ण है! मान लीजिए कि मैं लंबे समय तक आईएल में गोता लगा रहा हूं, मुझे शुभकामनाएं दीजिए।
जोड़ा लेखक Adam Tolley, स्रोत
यह वास्तव में एक टिप्पणी के रूप में उपयोगी नहीं है जैसा कि यह हो सकता है। मैंने आमंत्रित किया (जैसा कि मैं इसे समझता हूं ') उपयोगी व्याख्यान, सोचें कि आप थोड़ा और सामग्री प्रदान कर सकते हैं - क्योंकि लोग यहां जवाब की तलाश करते हैं और अपमान नहीं करते हैं। हालांकि, ऐसा लगता है कि मैं एक ही चीज़ का दोषी हो सकता हूं - मेरा वास्तव में उपर्युक्त टिप्पणी एक प्रश्न के रूप में है: क्या सी # संकलन समय पर इन चीजों का मूल्यांकन नहीं करता है?
जोड़ा लेखक Adam Tolley, स्रोत
सी # स्थिर रूप से टाइप किया गया है; पॉलिमॉर्फिक विधियों को कॉल संकलित समय पर भी बाध्य किया जाता है क्योंकि मैं इसे समझता हूं - यह कहना है कि सीएलआर रनटाइम के दौरान कॉल करने के लिए कौन सी विधि को हल करने के लिए नहीं छोड़ा गया है।
जोड़ा लेखक Adam Tolley, स्रोत

स्टेटिक विधियां तत्काल जैसी नहीं हैं, वे केवल ऑब्जेक्ट संदर्भ के बिना उपलब्ध हैं।

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

मुझे एक उदाहरण दिखाएं।

निम्नलिखित कोड के साथ:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

यदि आप बी.टेस्ट को कॉल करते हैं, तो इस तरह:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

फिर मुख्य विधि के अंदर वास्तविक कोड निम्नानुसार है:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

जैसा कि आप देख सकते हैं, कॉल ए.टेस्ट को बनाया गया है, क्योंकि यह ए क्लास था जिसने इसे परिभाषित किया था, न कि बी.टेस्ट के लिए, भले ही आप इस तरह कोड लिख सकें।

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

मुझे एहसास है कि आईएल डिजाइनर कोड को बी.टेस्ट पर कॉल करने के लिए संकलित करने की अनुमति दे सकते हैं, और रनटाइम पर कॉल को हल कर सकते हैं, लेकिन यह अभी भी वर्चुअल नहीं होगा, क्योंकि आपको अभी भी किसी प्रकार का क्लास नाम लिखना होगा।

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

इस प्रकार, वर्चुअल / अमूर्त स्थैतिक विधियां .NET में उपलब्ध नहीं हैं।

0
जोड़ा
जेनेरिक प्रकार पैरामीटर प्रभावी रूप से गैर-सतत "प्रकार" चर के रूप में व्यवहार करते हैं, और ऐसे संदर्भ में वर्चुअल स्थिर विधियां उपयोगी हो सकती हैं। उदाहरण के लिए, यदि किसी के पास कार टाइप वर्चुअल स्टेटिक CreateFromDescription फैक्ट्री विधि के साथ है, तो कोड जो कार -constrained जेनेरिक प्रकार <�कोड स्वीकार करता है > टी टी प्रकार की कार बनाने के लिए T.CreateFromDescription को कॉल कर सकता है। इस तरह के निर्माण को सीएलआर के भीतर बहुत अच्छी तरह से समर्थित किया जा सकता है यदि इस तरह की विधि को परिभाषित करने वाले प्रत्य
जोड़ा लेखक supercat, स्रोत
सी # में ऑपरेटर-ओवरलोडिंग के तरीके के साथ संयुक्त रूप से, यह दुर्भाग्यवश उप-वर्गों को किसी दिए गए ऑपरेटर ओवरलोड के लिए कार्यान्वयन प्रदान करने की आवश्यकता को समाप्त करता है।
जोड़ा लेखक Chris Moschini, स्रोत

हम वास्तव में स्थैतिक तरीकों (डेल्फी में) को ओवरराइड करते हैं, यह थोड़ा बदसूरत है, लेकिन यह हमारी आवश्यकताओं के लिए ठीक काम करता है।

हम इसका उपयोग करते हैं ताकि कक्षाएं कक्षा के उदाहरण के बिना उनकी उपलब्ध वस्तुओं की एक सूची हो सकती हैं, उदाहरण के लिए, हमारे पास ऐसा तरीका है जो इस तरह दिखता है:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

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

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

इसलिए प्रत्येक क्लाइंट के लिए एक अलग सर्वर एप्लिकेशन होने से बनाए रखना बहुत आसान है।

उम्मीद है कि उदाहरण स्पष्ट था।

0
जोड़ा

एक अन्य उत्तरदाता (मैकडॉवेल) ने कहा कि बहुरूपता केवल ऑब्जेक्ट उदाहरणों के लिए काम करती है। यह योग्य होना चाहिए; ऐसी भाषाएं हैं जो वर्गों को "कक्षा" या "मेटाक्लास" प्रकार के उदाहरण के रूप में मानती हैं। ये भाषाएं उदाहरण और कक्षा (स्थैतिक) दोनों विधियों के लिए बहुरूपता का समर्थन करती हैं।

सी #, जावा और सी ++ की तरह पहले, ऐसी भाषा नहीं है; static कीवर्ड स्पष्ट रूप से यह इंगित करने के लिए उपयोग किया जाता है कि विधि गतिशील / वर्चुअल के बजाय स्थिर रूप से बाध्य है।

0
जोड़ा

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

मान लीजिए कि आप एक पल के लिए स्थैतिक तरीकों का वारिस कर सकते हैं। इस परिदृश्य की कल्पना करो:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

यदि आप Base.GetNumber() को कॉल करते हैं, तो कौन सी विधि कहा जाएगा? कौन सा मूल्य लौटाया? यह देखना बहुत आसान है कि वस्तुओं के उदाहरण बनाये बिना, विरासत बल्कि कठिन है। विरासत के बिना सार विधियां केवल वे विधियां हैं जिनके पास शरीर नहीं है, इसलिए उन्हें नहीं कहा जा सकता है।

0
जोड़ा
@ArtemRussakovskii: मान लीजिए कि किसी के पास int DoSomething () था जहां टी: बेस {वापसी T.GetNumber ();} । यह उपयोगी प्रतीत होता है यदि DoSomething () पांच वापस कर सकता है, जबकि DoSomething () दो वापस आ जाएगा। ऐसी क्षमता न केवल खिलौनों के उदाहरणों के लिए उपयोगी होगी, बल्कि कुछ भी <�कोड> कक्षा कार {सार्वजनिक स्थैतिक वर्चुअल कार बिल्ड (खरीद ऑर्डर पीओ);} , जहां कार </कोड से प्राप्त हर वर्ग > एक ऐसी विधि को परिभाषित करना होगा जो खरीद आदेश दिए गए उदाहरण का निर्माण कर सके।
जोड़ा लेखक supercat, स्रोत
दुनिया में क्यों बेस होगा। गेटनंबर() कुछ और वापस लौटाएंगे लेकिन 5? यह बेस क्लास में एक विधि है - वहां केवल 1 विकल्प है।
जोड़ा लेखक Artem Russakovskii, स्रोत
गैर स्थैतिक विरासत के साथ बिल्कुल वही "समस्या" है।
जोड़ा लेखक Ark-kun, स्रोत
आपके परिदृश्य को देखते हुए मैं कहूंगा कि बेस। गेटनंबर() 5 वापस आ जाएगा; Child1.GetNumber() 1 लौटाता है; Child2.GetNumber() 2 लौटाता है; क्या आप मुझे तर्क साबित कर सकते हैं, मुझे आपकी तर्क समझने में मदद करने के लिए? धन्यवाद
जोड़ा लेखक Luis Filipe, स्रोत
चेहरा जो आपको लगता है बेस। गेटनंबर() 5 देता है, इसका मतलब है कि आप पहले से ही समझ रहे हैं कि क्या हो रहा है। मूल मूल्य लौटकर, कोई विरासत नहीं चल रही है।
जोड़ा लेखक David Wengier, स्रोत

अमूर्त विधियां पूरी तरह आभासी हैं। सार विधियों को एक उदाहरण की आवश्यकता होती है, लेकिन स्थिर विधियों में कोई उदाहरण नहीं है। तो, आप एक अमूर्त वर्ग में एक स्थिर विधि हो सकती है, यह स्थिर स्थिर (या सार स्थिर) नहीं हो सकता है।

0
जोड़ा
-1 वर्चुअल विधियों को डिज़ाइन को छोड़कर, उदाहरण की आवश्यकता नहीं है। और आप वास्तव में सवाल को संबोधित नहीं करते हैं, उतना ही इसे हटा दें।
जोड़ा लेखक TJMonk15, स्रोत

यहां एक ऐसी स्थिति है जहां स्थैतिक क्षेत्रों और विधियों के लिए निश्चित रूप से विरासत की आवश्यकता है:

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?
0
जोड़ा
नहीं, सरणी 'पैरों' का केवल एक उदाहरण है। आउटपुट नोडेटर्मेनिस्टिक है क्योंकि आप नहीं जानते कि स्थिर रचनाकारों को किस आदेश के लिए बुलाया जाएगा (वास्तव में बेस क्लास स्टेटिक कन्स्ट्रक्टर को बिल्कुल भी गारंटी नहीं दी जाएगी)। 'ज़रूरत' एक बिल्कुल पूर्ण शब्द है जहां 'इच्छा' शायद अधिक सटीक है।
जोड़ा लेखक Sam, स्रोत
<�कोड> पैर एक स्थिर सार संपत्ति होना चाहिए।
जोड़ा लेखक AbleArcher, स्रोत
वैसे यह मुझे स्थिर कन्स्ट्रक्टर कॉल करने के लिए मजबूर नहीं करता है। लेकिन मैं इसे अभी ले जाऊंगा ...
जोड़ा लेखक Evren Ozturk, स्रोत