2012-03-21 18 views
6

में स्थिर तरीकों मैं इस प्रासंगिक पोस्ट पढ़ा है, लेकिन कई ठोस जवाब नहीं थे (गरीब भाषा डिजाइन और अधिक या कम):, Why can't static methods be abstract in Javaसार स्काला

मैं स्काला के क्षेत्र में नये का एक सा कर रहा हूँ क्या यह संभव है (शायद लक्षण या कुछ के साथ)?

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

+1

क्या आप हमें अपने विशिष्ट परिदृश्य के बारे में कुछ और बता सकते हैं? साथी वस्तु में होने की विधि की आपको आवश्यकता क्यों है? स्कैला में ऐसा करने का एक अलग तरीका हो सकता है। –

+0

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

+0

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

उत्तर

4

स्कैला [*] में स्थिर तरीके नहीं हैं, इसलिए आपका प्रश्न मंथन है।

हालांकि, अगर आप एक विशेषता के साथ एक वस्तु का विस्तार करके आप क्या चाहते प्राप्त कर सकते हैं:

scala> trait A { def foo(): Int } 
defined trait A 

scala> object C extends A { def foo(): Int = 5 } 
defined module C 

scala> C.foo 
res0: Int = 5 

जो शायद आप क्या चाहते हैं नहीं करता है। किसी वर्ग के सहयोगी वस्तु में कुछ लागू करने के लिए वास्तव में कोई भी तरीका नहीं है। साथी वस्तु मौजूद नहीं हो सकती है।

[*] तकनीकी रूप से, लेकिन यह एक समग्र दर्शन की तुलना में एक कार्यान्वयन विस्तार से अधिक है। देखें Method in companion object compiled into static methods in scala?

+2

असल में, कॉमैनियन ऑब्जेक्ट के तरीकों को कक्षा के स्थिर तरीकों के रूप में देखा जा सकता है। – Nicolas

+2

@ निकोलस हां, कक्षा में एक स्थिर फॉरवर्डर है, लेकिन जैसा कि मैंने कहा, यह जावा के साथ इंटरऑप में मदद करने के लिए एक कार्यान्वयन विस्तार है।स्कैला भाषा में स्थिर विधियों की धारणा नहीं है। यह एक सिंगलटन का अधिक है। –

+0

यह कैसे संभव है कि साथी वस्तु मौजूद न हो? संकलन के समय यह नहीं पता होना चाहिए? –

0

स्कैला, जावा, सी ++ या सी # में अमूर्त स्थैतिक विधियां क्यों संभव नहीं हैं, इसके दो संभावित स्पष्टीकरण हैं।

पहला तकनीकी है: सार/वर्चुअल विधियों को किसी ऑब्जेक्ट के संदर्भ की आवश्यकता होती है (जिसे कहा जाता है) चलाने के लिए ओवरराइड चुनने के लिए। जब आप स्थैतिक विधि कहते हैं तो आप ऐसी कोई वस्तु प्रदान नहीं करते हैं।

दूसरा तार्किक है: सार/आभासी स्थैतिक विधियों का कोई अर्थ नहीं है। जब आप एक स्थिर विधि को कॉल करते हैं, तो आप हमेशा उस विधि को जानते हैं जिसमें वह विधि है। आप लिखते हैं:

MyClass.DoSomething(args) 

आप MyDerivative कि MyClass फैली है, तो आप सिर्फ एक और स्थिर विधि को परिभाषित कर सकते हैं:

MyDerivative.DoSomethingDifferent(args) 

सिर्फ स्थिर आभासी तरीकों का कोई मतलब नहीं है, क्योंकि वे बस के रूप में साधारण काम करेंगे स्थैतिक तरीकों।

+5

"स्थैतिक तरीकों को घटाएं", लोगों का अर्थ अक्सर उन तरीकों से होता है जिन्हें किसी भी ठोस उप-वर्ग द्वारा स्थिर रूप से कार्यान्वित किया जाना चाहिए। हालांकि मैं मानता हूं कि यह अच्छी तरह से आकार नहीं है, उनके अस्तित्व में वैध तर्क हैं। उदाहरण के लिए देखें कि कैसे स्कैला संग्रह "स्टेंडर्ड विधियों" के साथ एक साथी ऑब्जेक्ट के निर्माण को लागू करने का प्रयास करते हैं। – Nicolas

0

मुझे यकीन नहीं है कि आप जावा में एक अमूर्त स्थैतिक विधि के साथ क्या करना चाहते हैं, लेकिन अतीत में वर्णित एकमात्र संभावित उपयोग केस मैंने देखा है (मेरी इच्छा है कि मैं किसके द्वारा याद करता हूं ...) कॉल कर रहा है एक सामान्य प्रकार पैरामीटर पर सीधे एक विधि।

अर्थात जावा कुछ इस तरह ...

// this is not valid java... 
// let's pretend we can define a static method in an interface 
interface Foo { 
    static String Foo(); 
} 

// a class that implements our interface 
class FooImpl implements Foo { 
    public static String Foo() {return "foo";} 
} 

अनुमति अगर ...हम एक सामान्य पैरामीटर पर इसका इस्तेमाल कर सकता है,) सीधे प्रकार पर फू (कॉल करने के लिए

static <T extends Foo> String Test() { 
     return T.Foo(); // even if our hypothetical static interface 
         // was a valid thing, this would probably still fail 
         // due to type erasure  
} 

यह सी # में कुछ और अधिक समझ बनाने होता है क्योंकि:

  1. reified जेनरिक मतलब टाइप मिट नहीं प्राप्त करता है
  2. सी # ऑपरेटरों में स्थिर तरीके हैं और आप define your own operators

मूल रूप से यह एक "नाटक सी #" स्थिर इंटरफेस के साथ, आप somethi इस्तेमाल कर सकते हैं में इसका मतलब कर सकते हैं एनजी "उपरोक्त जावा" कोड से संबंधित एक जेनेरिक विधि लिखने के लिए जो किसी भी प्रकार पर काम करता है जो एक विशिष्ट ऑपरेटर को परिभाषित करता है (उदा। सबकुछ जिसमें "+" ऑपरेटर है)।

अब, स्कैला पर वापस जाएं। स्कैला इस परिदृश्य को कैसे संबोधित करता है? भाग में यह नहीं है। स्कैला में कोई स्थैतिक तरीका नहीं है: ऑब्जेक्ट एक सिंगलटन (यानी केवल एक उदाहरण वाला वर्ग है) लेकिन फिर भी सामान्य, उदाहरण विधियों वाला एक वर्ग, यानी ऑब्जेक्ट्स पर आप अभी भी एकमात्र उदाहरण पर विधियों को कॉल कर रहे हैं, सीधे प्रकार पर नहीं (यहां तक ​​कि ऑपरेटर स्केल में विधियां हैं)।

तो स्केला में हम लिखते थे:

trait Foo { def Foo:String } 
object FooImpl extends Foo { def Foo = "foo" } 

def Test(f: Foo) = f.Foo 

... और

scala> Test(FooImpl) 
res0: String = foo 
// note that FooImpl is still an instance (the only one) of FooImpl and not 
// the type itself 

के साथ हमारे विधि कॉल आप implicits एक पैरामीटर के रूप केवल उदाहरण गुजर से बचने के लिए के साथ कुछ चाल कर सकते हैं:

implicit def aFoo = FooImpl 
def Test2(implicit f: Foo) = f.Foo 

अब यह काम करता है:

+०१२३५१६४१०६१
scala> Test2 
res1: String = foo 

implicits के साथ अधिक उन्नत चाल के साथ, स्कैला भी संख्यात्मक परिभाषित करता है, allows you to use operators on any numeric value, भले ही वे बॉक्स के बाहर एक सामान्य इंटरफ़ेस लागू नहीं करते हैं।