I wrote a Scala class and defined the main() method in it. It compiled, but when I ran it, I got NoSuchMethodError:main. In all the scala examples, I have seen, the main method is defined in an object. In Java we define the main method in a class. Is it possible to define main() in a Scala class or do we always need an object for this?
To answer your question, have a look on the following :
I made a scala class, compiled and decompiled it, and what I got is interesting.
class MyScalaClass{
def main(args: Array[String]): Unit = {
println("Hello from main of class")
}
}
Compiled from "MyScalaClass.scala"
public class MyScalaClass {
public void main(java.lang.String[]);
public MyScalaClass();
}
So it means that when the scala class is converted to java class then the main method of the scala class which in turn being converted to the main method in java class is not static.
And hence we would not be able to run the program because JVM is not able to find the starting point in the program.
But if the same code is done by using the 'object' keyword then:
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[]);
}
So here we got public static void main in MyScalaClass.class therefore the main method can be executed directly by the JVM here.
I hope you got your answer.
As Eugene said in a comment, there are no static methods in Scala. But watch this:
$ 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[]);
}
Note that the classfile for the Echo class (not Echo$, the object) does indeed have a public static void main method. Scala generates static methods for methods defined in objects for compatibility with Java.
However, I consider creating a main method in a Scala program an anachronism. Use the App trait instead; it's cleaner:
object Echo extends App {
args foreach println
}
When I want to test my code in intelligent idea scala editor, I simply create a companion object just below my class and put a main method in it. That's all. see an example:
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)
}
}
Related
After the parser phase of the Scalac process, the following case class
case class ExampleCaseClass(var s:String, var i:Int) extends ContextuallyMutable
takes the intermediate form:
Clazz(case class ExampleCaseClass extends ContextuallyMutable with scala.Product with scala.Serializable {
<caseaccessor> <paramaccessor> var s: String = _;
<caseaccessor> <paramaccessor> var i: Int = _;
def <init>(s: String, i: Int) = {
super.<init>();
()
}
})
However, a run time reflection call:
ExampleCaseClass("Can a Scala compiler plugin transform the autogenerated accessor methods of scala case classes?", 42).getClass.getMethods.foreach(println(_))
reveals many more public methods:
public boolean ExampleCaseClass.equals(java.lang.Object)
public java.lang.String ExampleCaseClass.toString()
public int ExampleCaseClass.hashCode()
public static ExampleCaseClass ExampleCaseClass.apply(java.lang.String,int)
public int ExampleCaseClass.i()
public java.lang.String ExampleCaseClass.s()
public ExampleCaseClass ExampleCaseClass.copy(java.lang.String,int)
public void ExampleCaseClass.i_$eq(int)
public scala.collection.Iterator ExampleCaseClass.productElementNames()
public java.lang.String ExampleCaseClass.productElementName(int)
public void ExampleCaseClass.s_$eq(java.lang.String)
public int ExampleCaseClass.copy$default$2()
public boolean ExampleCaseClass.canEqual(java.lang.Object)
public java.lang.String ExampleCaseClass.productPrefix()
public int ExampleCaseClass.productArity()
public java.lang.Object ExampleCaseClass.productElement(int)
public scala.collection.Iterator ExampleCaseClass.productIterator()
public java.lang.String ExampleCaseClass.copy$default$1()
public static scala.Function1 ExampleCaseClass.tupled()
public static scala.Option ExampleCaseClass.unapply(ExampleCaseClass)
public static scala.Function1 ExampleCaseClass.curried()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
Clearly some subsequent compiler phase creates the property accessor methods:
public int ExampleCaseClass.i()
public java.lang.String ExampleCaseClass.s()
public void ExampleCaseClass.i_$eq(int)
public void ExampleCaseClass.s_$eq(java.lang.String)
Which compilation phase generates these accessor methods and what manner of compiler plugin (or other means) might prevent or transform them?
The enquirer has already run numerous experiments removing or reshaping the:
<caseaccessor> <paramaccessor> var s: String = _;
<caseaccessor> <paramaccessor> var i: Int = _;
portions of the case class, and also with injecting the desired accessor methods in advance but no combination has met the desired outcome. They either fail to compile because of naming conflicts that arise in subsequent compilation phases, or they alter the parameter names in constructor, apply, and accessor methods.
Can a scala compiler plugin transform synthetic accessors at all? Does the Java Compiler introduce these methods? If so, should the enquirer look to Javac plugins and what analogues might serve the Scala.js and Scala native compilation targets?
Thank you for any consideration.
case class expansion happens in more than one place, see another question.
Instead of writing a new plugin just to disallow using var it would be much better to add a new rule to Wartremover or ScalaFix. As a matter of the fact, these rules already exist:
disallow var with Wartremover - combine it with fatal warnings to fail compilation on var
disallow var with ScalaFix
If you want to add more elaborate rule... it would still be easier just to write your own Wartremover/ScalaFix rule (the latter might be preferred as it is already supported in Scala 3).
And if you really need a custom compiler plugin to mess with code generated by compiler... take a look at better-toString plugin. It adds its own phase after "parser" phase. But I wouldn't hope for removing the autogenerated implementations. At best you can override them manually where specs allows you to.
The enquirer found a Scala 3 solution with persistence and help from examples:
better-tostring a plugin that demonstrates conditional method insertion by Polyvariant.
Compiler Plugin Development in Scala 3 Example and Tutorial by Scala Center dev: Fengyun Liu. The video provided insights into compiler phases and the example shed light on method body generation syntax. In particular, available documentation doesn't readily clarify how to call println from a method body generated as a Tree by a compiler plugin, but Liu's example plugin demonstrated requireModule and requiredMethod.
Scala 3 Compiler Plugin Documentation offers a very nice template for how to start writing a plugin. The final solution looked very similar.
As of 26 Nov 2021, no solution exists for Scala 2.13, but maybe that just means it is time to upgrade.
final class BlockMutatorPlugin extends StandardPlugin {
override val name: String = "BlockMutatorPlugin"
override val description: String = "Scala Compiler Plugin for blocking ContextuallyMutable setter methods."
override def init(options: List[String]): List[PluginPhase] = List(new BlockContextuallyMutableSetters)
}
class BlockContextuallyMutableSetters extends PluginPhase {
val phaseName = "blockGetter"
/* Running this plugin after phases before ElimErasedValueType
resulted in the replacement of the generated setter methods by the synthetic
default versions. By the time that this ElimErasedValueType phase ends, the
defaults already existed, so this plugin could augment them safely. */
override val runsAfter = Set(ElimErasedValueType.name)
private var printBlocked: Tree = _
override def prepareForTemplate(tree: tpd.Template)(using ctx: Context): Context = {
val cnsl = requiredModule("scala.Predef")
val prntln: PreName = "println".toTermName
val say = cnsl.requiredMethod(prntln, List[Types.Type](ctx.definitions.ObjectType))
printBlocked = ref(say).appliedTo(Literal(Constant("Blocked!")))
ctx
}
override def transformTemplate(tree: Template)(using ctx: Context): Tree = {
if (tree.parents.filter(_.symbol.name.toString.equals("ContextuallyMutable")).nonEmpty) {
cpy.Template(tree)(
body = tree.body.collect {
case dd: DefDef if dd.name.isSetterName => DefDef(
dd.symbol.asInstanceOf[Symbols.TermSymbol],
printBlocked
)
case x => x
}
).asInstanceOf[Tree]
} else tree
}
}
The most important part of this effort involved discovering which compiler phase this plugin should follow. Similar efforts in Scala 2.13.6 have failed so far; the only remaining impediment to the Scala 2 solution sought by this original Stack Overflow question. As such, the enquirer will not mark his own answer as the accepted solution unless future edits avail Scala 2. Until that time, your response may claim that designation.
For any inclined to try compile this example, the code above requires the following import statements:
import dotty.tools.dotc.ast.tpd
import tpd.*
import dotty.tools.dotc.core.*
import Names.PreName
import Symbols.{ClassSymbol, requiredMethod, requiredModule}
import Decorators.*
import NameOps.*
import Contexts.Context
import Constants.Constant
import dotty.tools.dotc.plugins.*
import dotty.tools.dotc.transform.ElimErasedValueType
I have a class that contains a main method, and I wish to start a new process that runs this class.
But when I try to use Scala to get the name of this class, it gives me the wrong name. For example:
object Test {
def main(args: Array[String]) = {
println(Test.getClass.getCanonicalName)
}
}
Then:
roei#roei-main:~/Java$ scalac Test.scala
roei#roei-main:~/Java$ scala Test
Test$
roei#roei-main:~/Java$ javap Test*.class
Compiled from "Test.scala"
public final class Test {
public static void main(java.lang.String[]);
}
Compiled from "Test.scala"
public final class Test$ {
public static final Test$ MODULE$;
public static {};
public void main(java.lang.String[]);
}
Test.getClass.getCanonicalName gives me Test$, not Test. But the static main method is inside of a class named Test, whereas Test$ contains a non-static main. Obviously I can do the workaround of just deleting the $ at the end, but I'm looking for a more satisfying/reliable solution.
A possible solution would be using ClassTag of scala.reflect (see API). I mean something like the following:
import scala.reflect.ClassTag
import scala.reflect.classTag
class Test
object Test {
def main(args: Array[String]) = {
println(Test.getClass.getCanonicalName)
println(classTag[Test].runtimeClass.getCanonicalName)
}
}
it will print:
Test$
Test
Say in a scala file I define a class like
private class Test{}
what does the private here mean? In java you can't have a top level private class, which obviously makes sense. But private is syntactically valid in scala, hope someone can shed some light upon it.
You could specify package name for private modifier to allow access to this class only from specified package. By default (without package specified) it is visible only for other members in the enclosing package.
$ cat > test.scala <<EOF
package myPackage {
private[myPackage] class Test
private object A extends Test
}
package otherPackage {
object B extends myPackage.Test
}
EOF
$ scalac test.scala
test.scala:7: error: class Test in package myPackage cannot be accessed in package myPackage
object B extends myPackage.Test
^
one error found
For instance you can access private class from its companion object like this:
trait ITest
private class Test extends ITest
object Test {
def apply(): ITest = new Test
}
Test()
// ITest = Test#59e2abc3
Further clarification on examples:
package myPackage {
private class Test
private object A extends Test
object B extends myPackage.Test //Compile error: private class Test escapes its defining scope as part of type myPackage.Test
private object C extends myPackage.Test // works since C is also private
object Test {
def apply() = new Test //error: private class Test escapes its defining scope as part of type myPackage.Test
}
object Test2 {
def apply(): ITest = new Test //works as ITest is public
}
}
As long as instances of a private class do not escape the enclosing package scope it can be used within the package hierarchy. Companion objects accessing private classes has to be in same package hierarchy as well. With private[P] - p can be any package name that exists.
In Java I usually do something like:
class Hello {
public Hello() {
System.out.println("hello");
}
public static void main(String args[]) {
new Hello();
}
}
How do I do something similar in Scala? I start off with Hello being a Scala object like so:
object Hello {
// constructor goes here
def main(args: Array[String]): Unit = {
println("hello") // new Hello() would go here
}
}
but I can't instantiate that. If I change I change the object keyword to class then the scala compiler complains i.e.
class Hello {
println("hello")
def main(args: Array[String]): Unit = {
new Hello()
}
}
I know I'm probably on completely the wrong track here but I'd like to be put out of my misery.
Usually for this in Scala i use objects representing the application:
object Hello extends App {
println("hello")
}
I don't think you understand what a Scala object is. It is actually the equivalent of a Java singleton, where an anonymous class is created and instantiated in place.
If you would recompile the code to Java in this scenario:
object Hello {}
It would get something like:
public class Hello$ {
public static Hello$ $MODULE = new Hello$()
}
This is already a singleton, an equivalent of a val. You can even do:
val x = Hello; // x will be of type Hello.type
I asked a question earlier: here and although I accepted the answer I'm still very far from actually understanding, so I dug a bit deeper and I'm writing a further question.
The behaviour of overriding val in scala surprises me. For example, given this code:
class A {
val name = "AAAAA"
}
class B extends A {
override val name = "BBBBB"
}
if I say:
object Atest extends App {
val b = new B
println(b.name)
val a = b.asInstanceOf[A]
println(a.name)
}
I expect
BBBBB
AAAAA
but I get
BBBBB
BBBBB
I'm just trying to see the AAAAA value that I think A should be storing somewhere. So I try:
class A {
val name = "AAAAA"
def showSuper {
println(name)
}
}
and:
val b = new B
val a = b.asInstanceOf[A]
b.showSuper
a.showSuper
but I still get:
BBBBB
BBBBB
So I try do have a look at what scala is actually generating from my classes:
scalac -Xprint:all A.scala
gives me
class A extends Object {
private[this] val name: String = _;
<stable> <accessor> def name(): String = A.this.name;
def <init>(): p3.A = {
A.super.<init>();
A.this.name = "AAAAA";
()
}
};
class B extends p3.A {
private[this] val name: String = _;
override <stable> <accessor> def name(): String = B.this.name;
def <init>(): p3.B = {
B.super.<init>();
B.this.name = "BBBBB";
()
}
}
The call to B.super happens before B.this.name even gets set and A clearly sets its name to AAAAA.
What is going on? Why, when I override a val like this, can I not see A's value (or is it getting set to B's value?) What is the mechanism by which this happens? How can I see this mechanism - is there a piece of scala source code that shows me why this happens?
Many thanks
EDIT:
Meant to add that if I use javap to look at the bytecode, it clearly shows that A and B each have their own copy of the name variable:
$ javap -private A
Compiled from "A.scala"
public class p3.A extends java.lang.Object{
private final java.lang.String name;
public java.lang.String name();
public p3.A();
}
$ javap -private B
Compiled from "A.scala"
public class p3.B extends p3.A{
private final java.lang.String name;
public java.lang.String name();
public p3.B();
}
So it's not like A and B have to be sharing the same variable - they each have the potential for using their own copy.
That is not Scala specific. It is OOP question. The second class override the method and hides it.
Overriding and Hiding Methods
Just some extra notes. It transpires that if you decompile the scala classes, you find that scala changes references to vals to references to the methods that get the vals. For example where my class A above has:
def showSuper {
println(name)
}
the decompiled bytecode shows
public void showSuper()
{
Predef..MODULE$.println(name());
}
(thanks to jd-gui)
So this makes it clear that scala references to vals are equivalent in bytecode to java's polymorphic method calls rather than java's variables which are type dependent.