2009-02-05 16 views
24

परिभाषित किए बिना एक अमूर्त वर्ग का एक उदाहरण बनाना मुझे पता है कि यह जावा में किया जा सकता है, क्योंकि मैंने इस तकनीक का उपयोग अतीत में काफी व्यापक रूप से किया है। जावा में एक उदाहरण नीचे दिखाया जाएगा। यह भी सी # में किया जा सकता (अतिरिक्त प्रश्न। क्या इस तकनीक कहा जाता है? यह एक नाम के बिना इस का एक उदाहरण खोजने के लिए मुश्किल है।)सी #: नई कक्षा

public abstract class Example { 
    public abstract void doStuff(); 
} 

public class StartHere{ 
    public static void main(string[] args){ 
     Example x = new Example(){ 
     public void doStuff(){ 
      System.out.println("Did stuff"); 
     }    
     }; 
     x.doStuff(); 
    } 
} 

अब, अपने मुख्य सवाल होगा, और यदि हां, तो कैसे?

उत्तर

16

लांबा भाव और वर्ग के साथ प्रारंभिक आप थोड़ा सा प्रयास के साथ एक ही व्यवहार प्राप्त कर सकते हैं। इस समाधान है कि मैं सिर्फ महसूस किया साथ

public class Example { 
    public Action DoStuff; 
    public Action<int> DoStuffWithParameter; 
    public Func<int> DoStuffWithReturnValue; 
} 

class Program { 
    static void Main(string[] args) { 
     var x = new Example() { 
      DoStuff =() => { 
       Console.WriteLine("Did Stuff"); 
      }, 
      DoStuffWithParameter = (p) => { 
       Console.WriteLine("Did Stuff with parameter " + p); 
      }, 
      DoStuffWithReturnValue =() => { return 99; } 


     }; 

     x.DoStuff(); 
     x.DoStuffWithParameter(10); 
     int value = x.DoStuffWithReturnValue(); 
     Console.WriteLine("Return value " + value); 
     Console.ReadLine(); 
    } 
} 

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

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

पीएस यदि आप एक उत्तर देने के लिए जा रहे हैं, तो हम सभी को एक एहसान दें और इस बात से कोई टिप्पणी जोड़ें कि आप असहमत क्यों हैं :-)

+2

यह ** नहीं है * * वही व्यवहार। अनाम आंतरिक कक्षाओं के बारे में सबसे उपयोगी हिस्सा लैम्बडा अभिव्यक्तियों के बारे में गलत जानकारी के लिए – makhdumi

21

जावा तकनीक को "Anonymous inner class" कहा जाता है, और सी # में कोई समकक्ष नहीं है।

8

यह सी # में नहीं किया जा सकता है; आपको एक नया वर्ग प्रकार घोषित करने की आवश्यकता है।

public class StartHere{ 
    private class Foo : Example { 
     public override void doStuff() 
     { 
      Console.WriteLine("did stuff"); 
     } 
    } 
    public static void Main(string[] args){ 
     Example x = new Foo(); 
     x.doStuff(); 
    } 
} 
+0

यह उल्लेख है कि सी # में एक आंतरिक 'निजी class' से मेल खाएंगे लायक है जावा के' निजी स्थैतिक वर्ग 'आंतरिक वर्ग, और इस प्रकार युक्त वर्ग के सदस्यों तक नहीं पहुंच सकता है। –

+0

@ जीन-फिलिपपेलेट जो सच नहीं है; सी # * में 'निजी वर्ग 'के पास * वर्ग * (यहां तक ​​कि' निजी 'सदस्यों) के * सदस्यों * तक पहुंच है। इसमें कमी का वर्ग * एक * उदाहरण है। यदि नेस्टेड क्लास में एक उदाहरण उपलब्ध कराया जाता है, तो नेस्टेड क्लास में सदस्यों तक पूर्ण पहुंच होती है। –

+0

ठीक है, स्पष्टीकरण के लिए धन्यवाद; मैंने अपनी सजा सुनाई (और "पहुंच" शब्द का इस्तेमाल किया) बुरी तरह से! –

0

संक्षेप में नहीं, तुम अलग उप वर्ग के रूप में यह परिभाषित करने के लिए है: निकटतम आप सी # में प्राप्त कर सकते हैं शायद एक नामित नेस्टेड वर्ग है। मुझे लगता है कि यह सुविधा सी # 4.0 आ रही है हालांकि?

संपादित करें: नहीं, यह नहीं आया सी # 4.0 मैंने इसे बनाया है।

+0

मुझे उन विशेषताओं के साथ सी # 4.0 में कुछ भी पता नहीं है। –

+0

यह गतिशील कीवर्ड था जिसे मैं –

+0

डर्न के बारे में सोच रहा था ... आप मुझे उत्साहित कर चुके थे ... मैंने किसी भी आधिकारिक "आंतरिक कक्षा सी # 4.0" संदर्भों के लिए उच्च और निम्न खोज की, लेकिन कोई भी नहीं था ;-(भरपूर लोगों को यह चाहते हैं हालांकि ... –

0

आप इसे .NET में मॉकिंग के साथ पूरा करने में सक्षम हैं। हालांकि इस सुविधा के लिए कोई भाषा समर्थन नहीं है, मुझे लगता है कि यह सी # 4.0 में उपलब्ध होगा। वहाँ पुस्तकालयों के एक नंबर सहित, मजाक के लिए वहाँ बाहर हैं:

1

यह सी # में समर्थित नहीं है, और अगर यह मेरे पास थे ऐसा नहीं होना चाहिए या तो।

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

(वैसे हम में से एक बहुत कुछ इस एक हाथ खेल में काफी अच्छा मिल गया है, और अब ऐसा लगता है जैसे हम कम से कम बंद के लिए जावा 8 तक इंतजार करना है ...)

+1

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

10

आमतौर पर, जावा में अज्ञात आंतरिक कक्षाओं के साथ हल की जाने वाली समस्याओं को एक बहुत साफ फैशन में हल किया जाता है .NET में प्रतिनिधियों का उपयोग करना। आपका इरादा निर्धारित करने के लिए आपका उदाहरण थोड़ा सा सरल है।यदि अमूर्त वर्ग का उपयोग करके आपका इरादा किसी "व्यवहार" के आसपास गुजरना है, तो इसके बजाय केवल Action प्रतिनिधि का उपयोग करने के बारे में सोचें।

public class StartHere{ 
    public static void main(string[] args){ 
     Action doStuff =() => Console.WriteLine("Did stuff"); 
     executeSomething(doStuff); 
    } 

    public static void executeSomething(Action action) 
    { 
     action(); 
    } 
} 
1

जबकि सब अच्छा जवाब है, काम का सुझाव दिया arounds के अधिकांश, सी # 3.0

तो पर भरोसा करते हैं पूर्णता के लिए के लिए, मैं एक और समाधान न lambdas और न ही समारोह प्रकार का उपयोग करता है जोड़ देंगे (दी कि , जैसा मैट ओलेनिक ने टिप्पणियों में उल्लेख किया है, वैसे ही नीचे दिए गए प्रतिनिधियों को समान तरीके से काम करने के लिए सामान्यीकृत किया जा सकता है।)। उन लोगों के लिए, मेरे जैसे जो अभी भी सी # 2.0 के साथ काम कर रहे हैं। शायद सबसे अच्छा समाधान नहीं है, लेकिन यह काम करता है।

public delegate void Action(); 

यह अपनी कक्षा की सटीक बराबर है:

public class Example 
{ 
    public delegate void DoStuffDelecate(); 
    public DoStuffDelecate DoStuff; 
    public delegate void DoStuffWithDelecate(int n); 
    public DoStuffWithDelecate DoStuffWithParameter; 
    public delegate int DoStuffWithReturnDelecate(); 
    public DoStuffWithReturnDelecate DoStuffWithReturnValue; 
} 

class Program 
{ 
    static int MethodWithReturnValue() 
    { 
     return 99; 
    } 
    static void MethodForDelecate() 
    { 
     Console.WriteLine("Did Stuff"); 
    } 
    static void MethodForDelecate(int n) 
    { 
     Console.WriteLine("Did Stuff with parameter " + n); 
    } 


    static void Main(string[] args) 
    { 
     var x = new Example(); 
     x.DoStuff = MethodForDelecate; 
     x.DoStuffWithParameter = MethodForDelecate; 
     x.DoStuffWithReturnValue = MethodWithReturnValue; 

     x.DoStuff(); 
     x.DoStuffWithParameter(10); 
     int value = x.DoStuffWithReturnValue(); 
     Console.WriteLine("Return value " + value); 
     Console.ReadLine(); 
    } 
} 
+0

-1 को पूरी तरह से परिभाषित किए बिना कक्षा को विस्तारित करने में सक्षम है। उन्हें केवल .NET 3.5 की आवश्यकता नहीं है सी # 3.0. सी # 3.0 कंपाइलर .NET 2.0 को लक्षित कर सकता है। लैम्ब्डा एक्सप्रेशन केवल प्रतिनिधियों के लिए सिंटैक्टिक चीनी हैं। और हालांकि Func प्रकार System.Core के बाहर मौजूद नहीं है, लेकिन आप आसानी से समकक्ष परिभाषित कर सकते हैं। –

+0

दाएं। मुझे उम्मीद है कि यह अधिक सटीक है। मैं स्वयं एएसपी.नेट परियोजना पर काम कर रहा हूं, और मुझे इस्तेमाल किए गए फ्रेमवर्क को अलग-अलग परिभाषित करने और सी # कंपाइलर का उपयोग करने का कोई तरीका नहीं मिला है, इसलिए पिछला जवाब मैं अपने स्वयं के उत्थान और ऑफिकल दस्तावेज के साथ अपनाना चाहता था। – vipirtti

1

के बाद से अपनी कक्षा केवल एक कार्रवाई का प्रतिनिधित्व करता है, तो आप अपने मामले में एक प्रतिनिधि का उपयोग कर सकते हैं, वहाँ एक मौजूदा प्रतिनिधि है।

और अपने गुमनाम वर्ग की घोषणा भी क्लीनर है:

Action action =() => Console.WriteLine("Hello world"); 
action(); // invoke 

तुम भी बंद का उपयोग कर सकते हैं:

public void Hello(string name) 
{ 
    Action action =() => Console.WriteLine("Hello " + name); 
    action(); // will call the above lambda ! 
} 
संबंधित मुद्दे