How Scala App trait and main works internally?












0















Hi I'm newbie in Scala.



As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.



I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...



The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.



But the What confusing me are




  1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)

  2. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.

  3. Where can I check these knowledge? I tried to search in document but I couldn't










share|improve this question



























    0















    Hi I'm newbie in Scala.



    As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.



    I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...



    The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.



    But the What confusing me are




    1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)

    2. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.

    3. Where can I check these knowledge? I tried to search in document but I couldn't










    share|improve this question

























      0












      0








      0








      Hi I'm newbie in Scala.



      As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.



      I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...



      The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.



      But the What confusing me are




      1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)

      2. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.

      3. Where can I check these knowledge? I tried to search in document but I couldn't










      share|improve this question














      Hi I'm newbie in Scala.



      As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.



      I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...



      The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.



      But the What confusing me are




      1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)

      2. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.

      3. Where can I check these knowledge? I tried to search in document but I couldn't







      scala






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 25 '18 at 14:12









      Hacking JHacking J

      11910




      11910
























          2 Answers
          2






          active

          oldest

          votes


















          5
















          1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)




          The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.





          1. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.




          Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.





          1. Where can I check these knowledge? I tried to search in document but I couldn't.




          I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved



          I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.



          First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.



          Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.



          So for a class:



          class Foo {
          // code.
          def method = ???
          }


          Whatever code is, it will be executed automatically when you call new Foo.



          In case of an object



          object Foo {
          // code.
          def method = ???
          }


          The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.



          So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.



          Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.



          The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.



          Basically it rewrites this:



          object Foo {
          // some code
          }


          into



          object Foo {
          // delayedInt({some code})
          }


          This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.



          So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.



          Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.



          As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.



          The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:




          1. It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.

          2. It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.


          The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.



          Basically it turns this:



          object Foo {
          // some code
          }


          into this



          object Foo {

          // the implementation of delayedInt is to put `// some code` into a list buffer
          delayedInt (// some code)

          def main(args: Array[String]) = {
          // the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
          ???
          }
          }


          So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.



          Given the following code snippet:



          class AnotherClass {
          println("Initialising AnotherClass")
          }
          trait AnotherTrait {
          println("Initialising AnotherTrait")
          }
          trait YetAnotherTrait {
          println("Initialising YetAnotherTrait")
          }

          object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
          println("Hello world")
          }


          When run would output the following:



          Initialising AnotherClass
          Initialising AnotherTrait
          Initialising YetAnotherTrait
          Hello world


          So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.



          As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.






          share|improve this answer





















          • 1





            Perfect answer! I appreciate it

            – Hacking J
            Nov 25 '18 at 23:19



















          0














          delayedInit:-




          The init hook. This saves all initialization code for execution within
          main. This method is normally never called directly from user code.
          Instead it is called as compiler-generated code for those classes and
          objects (but not traits) that inherit from the DelayedInit trait and
          that do not themselves define a delayedInit method.




          App scala



          delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.



          initCodes:-



          I am not sure about the reason for defining the initCodes as ListBuffer.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53468358%2fhow-scala-app-trait-and-main-works-internally%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            5
















            1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)




            The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.





            1. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.




            Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.





            1. Where can I check these knowledge? I tried to search in document but I couldn't.




            I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved



            I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.



            First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.



            Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.



            So for a class:



            class Foo {
            // code.
            def method = ???
            }


            Whatever code is, it will be executed automatically when you call new Foo.



            In case of an object



            object Foo {
            // code.
            def method = ???
            }


            The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.



            So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.



            Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.



            The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.



            Basically it rewrites this:



            object Foo {
            // some code
            }


            into



            object Foo {
            // delayedInt({some code})
            }


            This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.



            So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.



            Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.



            As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.



            The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:




            1. It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.

            2. It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.


            The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.



            Basically it turns this:



            object Foo {
            // some code
            }


            into this



            object Foo {

            // the implementation of delayedInt is to put `// some code` into a list buffer
            delayedInt (// some code)

            def main(args: Array[String]) = {
            // the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
            ???
            }
            }


            So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.



            Given the following code snippet:



            class AnotherClass {
            println("Initialising AnotherClass")
            }
            trait AnotherTrait {
            println("Initialising AnotherTrait")
            }
            trait YetAnotherTrait {
            println("Initialising YetAnotherTrait")
            }

            object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
            println("Hello world")
            }


            When run would output the following:



            Initialising AnotherClass
            Initialising AnotherTrait
            Initialising YetAnotherTrait
            Hello world


            So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.



            As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.






            share|improve this answer





















            • 1





              Perfect answer! I appreciate it

              – Hacking J
              Nov 25 '18 at 23:19
















            5
















            1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)




            The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.





            1. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.




            Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.





            1. Where can I check these knowledge? I tried to search in document but I couldn't.




            I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved



            I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.



            First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.



            Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.



            So for a class:



            class Foo {
            // code.
            def method = ???
            }


            Whatever code is, it will be executed automatically when you call new Foo.



            In case of an object



            object Foo {
            // code.
            def method = ???
            }


            The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.



            So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.



            Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.



            The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.



            Basically it rewrites this:



            object Foo {
            // some code
            }


            into



            object Foo {
            // delayedInt({some code})
            }


            This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.



            So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.



            Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.



            As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.



            The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:




            1. It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.

            2. It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.


            The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.



            Basically it turns this:



            object Foo {
            // some code
            }


            into this



            object Foo {

            // the implementation of delayedInt is to put `// some code` into a list buffer
            delayedInt (// some code)

            def main(args: Array[String]) = {
            // the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
            ???
            }
            }


            So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.



            Given the following code snippet:



            class AnotherClass {
            println("Initialising AnotherClass")
            }
            trait AnotherTrait {
            println("Initialising AnotherTrait")
            }
            trait YetAnotherTrait {
            println("Initialising YetAnotherTrait")
            }

            object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
            println("Hello world")
            }


            When run would output the following:



            Initialising AnotherClass
            Initialising AnotherTrait
            Initialising YetAnotherTrait
            Hello world


            So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.



            As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.






            share|improve this answer





















            • 1





              Perfect answer! I appreciate it

              – Hacking J
              Nov 25 '18 at 23:19














            5












            5








            5









            1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)




            The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.





            1. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.




            Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.





            1. Where can I check these knowledge? I tried to search in document but I couldn't.




            I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved



            I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.



            First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.



            Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.



            So for a class:



            class Foo {
            // code.
            def method = ???
            }


            Whatever code is, it will be executed automatically when you call new Foo.



            In case of an object



            object Foo {
            // code.
            def method = ???
            }


            The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.



            So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.



            Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.



            The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.



            Basically it rewrites this:



            object Foo {
            // some code
            }


            into



            object Foo {
            // delayedInt({some code})
            }


            This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.



            So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.



            Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.



            As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.



            The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:




            1. It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.

            2. It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.


            The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.



            Basically it turns this:



            object Foo {
            // some code
            }


            into this



            object Foo {

            // the implementation of delayedInt is to put `// some code` into a list buffer
            delayedInt (// some code)

            def main(args: Array[String]) = {
            // the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
            ???
            }
            }


            So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.



            Given the following code snippet:



            class AnotherClass {
            println("Initialising AnotherClass")
            }
            trait AnotherTrait {
            println("Initialising AnotherTrait")
            }
            trait YetAnotherTrait {
            println("Initialising YetAnotherTrait")
            }

            object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
            println("Hello world")
            }


            When run would output the following:



            Initialising AnotherClass
            Initialising AnotherTrait
            Initialising YetAnotherTrait
            Hello world


            So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.



            As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.






            share|improve this answer

















            1. Who call delayedInit? Is it called before the main method is called?(I guess Yes)




            The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.





            1. Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.




            Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.





            1. Where can I check these knowledge? I tried to search in document but I couldn't.




            I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved



            I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.



            First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.



            Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.



            So for a class:



            class Foo {
            // code.
            def method = ???
            }


            Whatever code is, it will be executed automatically when you call new Foo.



            In case of an object



            object Foo {
            // code.
            def method = ???
            }


            The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.



            So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.



            Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.



            The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.



            Basically it rewrites this:



            object Foo {
            // some code
            }


            into



            object Foo {
            // delayedInt({some code})
            }


            This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.



            So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.



            Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.



            As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.



            The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:




            1. It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.

            2. It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.


            The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.



            Basically it turns this:



            object Foo {
            // some code
            }


            into this



            object Foo {

            // the implementation of delayedInt is to put `// some code` into a list buffer
            delayedInt (// some code)

            def main(args: Array[String]) = {
            // the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
            ???
            }
            }


            So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.



            Given the following code snippet:



            class AnotherClass {
            println("Initialising AnotherClass")
            }
            trait AnotherTrait {
            println("Initialising AnotherTrait")
            }
            trait YetAnotherTrait {
            println("Initialising YetAnotherTrait")
            }

            object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
            println("Hello world")
            }


            When run would output the following:



            Initialising AnotherClass
            Initialising AnotherTrait
            Initialising YetAnotherTrait
            Hello world


            So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.



            As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 25 '18 at 21:47

























            answered Nov 25 '18 at 19:32









            dadedade

            1,45731932




            1,45731932








            • 1





              Perfect answer! I appreciate it

              – Hacking J
              Nov 25 '18 at 23:19














            • 1





              Perfect answer! I appreciate it

              – Hacking J
              Nov 25 '18 at 23:19








            1




            1





            Perfect answer! I appreciate it

            – Hacking J
            Nov 25 '18 at 23:19





            Perfect answer! I appreciate it

            – Hacking J
            Nov 25 '18 at 23:19













            0














            delayedInit:-




            The init hook. This saves all initialization code for execution within
            main. This method is normally never called directly from user code.
            Instead it is called as compiler-generated code for those classes and
            objects (but not traits) that inherit from the DelayedInit trait and
            that do not themselves define a delayedInit method.




            App scala



            delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.



            initCodes:-



            I am not sure about the reason for defining the initCodes as ListBuffer.






            share|improve this answer




























              0














              delayedInit:-




              The init hook. This saves all initialization code for execution within
              main. This method is normally never called directly from user code.
              Instead it is called as compiler-generated code for those classes and
              objects (but not traits) that inherit from the DelayedInit trait and
              that do not themselves define a delayedInit method.




              App scala



              delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.



              initCodes:-



              I am not sure about the reason for defining the initCodes as ListBuffer.






              share|improve this answer


























                0












                0








                0







                delayedInit:-




                The init hook. This saves all initialization code for execution within
                main. This method is normally never called directly from user code.
                Instead it is called as compiler-generated code for those classes and
                objects (but not traits) that inherit from the DelayedInit trait and
                that do not themselves define a delayedInit method.




                App scala



                delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.



                initCodes:-



                I am not sure about the reason for defining the initCodes as ListBuffer.






                share|improve this answer













                delayedInit:-




                The init hook. This saves all initialization code for execution within
                main. This method is normally never called directly from user code.
                Instead it is called as compiler-generated code for those classes and
                objects (but not traits) that inherit from the DelayedInit trait and
                that do not themselves define a delayedInit method.




                App scala



                delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.



                initCodes:-



                I am not sure about the reason for defining the initCodes as ListBuffer.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 25 '18 at 18:51









                notionquestnotionquest

                17.5k13152




                17.5k13152






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53468358%2fhow-scala-app-trait-and-main-works-internally%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Wiesbaden

                    Marschland

                    Dieringhausen