2014-05-01 4 views
23

में मुख्य विधि मैंने स्कैला वर्ग लिखा और main() विधि को परिभाषित किया। यह संकलित, लेकिन जब मैं इसे चला गया, मुझे NoSuchMethodError:main मिला। सभी स्कैला उदाहरणों में, मैंने देखा है, मुख्य विधि को किसी ऑब्जेक्ट में परिभाषित किया गया है। जावा में हम एक वर्ग में मुख्य विधि को परिभाषित करते हैं। क्या स्केल क्लास में main() को परिभाषित करना संभव है या क्या हमें इसके लिए हमेशा एक ऑब्जेक्ट चाहिए?स्कैला

+7

यह केवल ऑब्जेक्ट है। जावा में यह वास्तव में स्थिर विधि मुख्य है। लेकिन स्कैला में कोई 'स्थैतिक' विधियां नहीं हैं। –

+0

@EugeneZhulenev: यह एक जवाब है ... –

+0

क्या ऑब्जेक्ट को ऐप भी विस्तारित नहीं करना है? – Totoro

उत्तर

14

जैसा कि यूजीन ने एक टिप्पणी में कहा था, स्कैला में कोई स्थैतिक विधियां नहीं हैं। लेकिन इस घड़ी:

$ cat Echo.scala 
object Echo { 
    def main(args:Array[String]):Unit = args foreach println 
} 

$ scalac Echo.scala 

$ javap Echo\$.class 
Compiled from "Echo.scala" 
public final class Echo$ { 
    public static final Echo$ MODULE$; 
    public static {}; 
    public void main(java.lang.String[]); 
} 

$ javap Echo.class 
Compiled from "Echo.scala" 
public final class Echo { 
    public static void main(java.lang.String[]); 
} 

ध्यान दें कि इको वर्ग के लिए classfile ($ गूंज नहीं, वस्तु) वास्तव में एक public static void मुख्य विधि है। स्कैला जावा के साथ संगतता के लिए वस्तुओं में परिभाषित विधियों के लिए स्थैतिक तरीकों को उत्पन्न करता है।

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

object Echo extends App { 
    args foreach println 
} 
+0

दुर्भाग्यवश 'ऐप' का उपयोग करने में अन्य समस्याएं हैं: http://stackoverflow.com/questions/29133161/scala-member-field-visibility-in-spark-jobs। लेकिन इसके लिए, मैं मानता हूं कि ऐप सैद्धांतिक रूप से क्लीनर है। –

32

आपके प्रश्न का उत्तर करने के लिए निम्न पर एक नजर है: मैं एक स्केला वर्ग बनाया संकलित और यह decompiled, और क्या मुझे मिल दिलचस्प है।

class MyScalaClass{ 
    def main(args: Array[String]): Unit = { 
     println("Hello from main of class") 
    }enter code here 
} 

Compiled from "MyScalaClass.scala" 

public class MyScalaClass { 
     public void main(java.lang.String[]); 
     public MyScalaClass(); 
} 

तो इसका मतलब है कि जब स्केला वर्ग जावा वर्ग में बदल जाती है तो स्केला वर्ग है जो बदले में जावा वर्ग में मुख्य विधि में बदला जा रहा की मुख्य विधि स्थिर नहीं है। और इसलिए हम प्रोग्राम चलाने में सक्षम नहीं होंगे क्योंकि JVM प्रोग्राम में प्रारंभिक बिंदु नहीं ढूंढ पा रहा है।

लेकिन एक ही कोड 'वस्तु' कीवर्ड तो का उपयोग करके किया गया है:

Compiling the following: 

object MyScalaClass{ 
def main(args: Array[String]): Unit = { 
    println("Hello from main of object") 
} 
} 

Decompiling the following: 
javap MyScalaClass$.class 

Compiled from "MyScalaClass.scala" 
public final class MyScalaClass$ { 
public static final MyScalaClass$ MODULE$; 
public static {}; 
public void main(java.lang.String[]); 
} 

Decompiling the following 
javap MyScalaClass.class 

Compiled from "MyScalaClass.scala" 
public final class MyScalaClass { 
    public static void main(java.lang.String[]); 
} 

तो यहाँ हमारे पास public static void मैं MyScalaClass.class में इसलिए मुख्य विधि क्रियान्वित किया जा सकता सीधे जेवीएम द्वारा यहां।

मुझे आशा है कि आपको अपना जवाब मिल जाएगा।

0

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

class Colon { 
    class Cow { 
     def^(moon:Moon): Unit ={ 
     println("Cow jumped over the moon") 
     } 
    } 
    class Moon{ 
     def ^:(cow:Cow) = println("This cow jumped over moon too") 
    } 
} 
object Colon{ 
    def main(args: Array[String]): Unit = { 
    val c:Colon = new Colon 
    val cow = new c.Cow 
    val moon = new c.Moon 
    cow^moon 
    cow ^: moon 
    moon.^:(cow) 
    } 
}