-1

Is there a way I can compile a main() method statically inside an existing class in Kotlin? I'm trying to get Gradle to build this as an application with a main() method, but I'm having no luck. I've been trying several workarounds too...

class MyApp: App() {

    override val primaryView = MyView::class

    companion object Launcher {
        @JvmStatic
        fun main(args: Array<String>): Unit {
            launch(*args)
        }
    }
}

In my Gradle script, I am trying to specify the MyApp class has a main() method. It errors out and can't find the class however when I call run.

mainClassName = 'path.to.application.MyApp'

EDIT

I apologize for the confusion but part of my issue might have to do with subclassing and not necessarily finding the main() class.

The main() function needs access to the launch() method that is defined in App. For some reason putting the companion keyword disallows this :/ Can we rethink the downvotes if this information is relevant?

tmn
  • 11,121
  • 15
  • 56
  • 112
  • I think you need 'path.to.application.MyApp.Companion' – CaseyB Mar 02 '16 at 15:41
  • 1
    Is the package for `MyApp` the same as `path.to.application`? In Kotlin package directives do not have to match file locations. – mfulton26 Mar 02 '16 at 15:50
  • 1
    The `mainClassName` is correct assuming the `path.to.application` is the correct package name. Naming the companion or not doesn't affect the static method which is placed on `MyApp` always. You can check this in Intellij by right clicking on the main and picking `create com.bla.bla...` for a new configuration and seeing the class name chosen. You don't show the package name for sure of `MyApp` and you do not show the exact error you get. So we cannot be sure. Please share the missing pieces of the puzzle. – Jayson Minard Mar 02 '16 at 16:01
  • Possible duplicate of [how to run compiled class file in Kotlin?](http://stackoverflow.com/questions/9355690/how-to-run-compiled-class-file-in-kotlin) – Jayson Minard Mar 02 '16 at 16:17
  • Your question is misleading if your answer was successful. Because you actually tried to run `path.to.application.MyApp.Launcher` but didn't say that. Otherwise the code below would not work. Remove `Launcher` from the `mainClassName` and also from the companion object name, it isn't needed and is what confused you. – Jayson Minard Mar 02 '16 at 16:24
  • Please edit the question if you indeed were using a different `mainClassName` – Jayson Minard Mar 02 '16 at 16:28
  • I think there might be a detail we all are overlooking. Are we accounting for the fact that `Launcher` is not a subclass of `App`? It seems to have a problem with `companion` objects and I get an error indicating the subclass issue. It does find the `main()` function though. When `companion` is removed it works fine. – tmn Mar 02 '16 at 16:43
  • Updated question. Please rethink your guys' downvotes if the new info is relevant. Sorry my question was misleading and I was confusing two types of errors. – tmn Mar 02 '16 at 16:48
  • So the code didn't compile in the first place, and had an error message? – Jayson Minard Mar 02 '16 at 17:23
  • your reference to downvotes: it might be due to it being a duplicate question more than the content, it is never clear why people downvote and best just to move along without taking it personally. Everyone gets them. – Jayson Minard Mar 02 '16 at 17:25
  • to use `launch()` method you would change to `MyApp().launch(*args)` – Jayson Minard Mar 02 '16 at 17:26
  • I address this as well in my answer below. – Jayson Minard Mar 02 '16 at 17:28
  • In the future if you include things like the actual error messages, package names, if it compiled, errors if not, ... then people can help you more quickly, and you might find the answer just by collecting that evidence. Never summarize an important detail. – Jayson Minard Mar 02 '16 at 17:30

1 Answers1

3

A static method in a companion object is placed onto the enclosing class. So in your case MyApp. This is true regardless of you naming the companion object, and you do not need to reference the companion in any way when running the class.

Therefore your code is correct, assuming the following is true:

  1. You have the application plugin applied in your Gradle
  2. You named your package containing the code above as path.to.application (you don't show package statement)
  3. You are getting a class not found error for path.to.application.MyApp and that matches #2, (you don't show the actual error from Gradle)
  4. You are running the correct gradle task (which task are you running?)
  5. The code is actually compiled, looking at your latest comments indicates you likely had a compiler error (launch() method not accessible from companion) which meant that you couldn't run something not yet compiled.

What you can do to check the classname is right click on the main() method within Intellij IDEA and pick create path.to.app... menu option that is just below run/debug options and when that opens the runtime configuration dialog you can see the full classname there. That should be the same one used in your Gradle. If you already have a runtime configuration, just view the full classname there. If this does not work, the problem is elsewhere and you need to provide the missing information (what Gradle task, what is the actual error, what is the package statement for the class)

Some information is missing from the question that would help narrow this down.

This example:

package org.test.kotlin

class MyApp {
    companion object Launcher {
        @JvmStatic
        fun main(args: Array<String>) {
            println("hello")
        }
    }
}

Works fine when running class org.test.kotlin.MyApp

So does this, without the word Launcher:

package org.test.kotlin

class MyApp {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            println("hello")
        }
    }
}

And this works by accident but is not doing what you expected, but is creating a nested class and adding the static there and run using class org.test.kotlin.MyApp.Launcher. If this is working, then the question isn't showing the actual main classname it is using that is failing:

package org.test.kotlin

class MyApp {
    object Launcher {
        @JvmStatic
        fun main(args: Array<String>) {
            println("hello")
        }
    }
}

About possible compiler errors (#5 above): In your code you reference the launch() method which you do not show, maybe it is in the ancestor class. But you did not create an instance of any class. So this will fail with compiler error. Change this to:

class MyApp: App() {
    override val primaryView = MyView::class
    companion object {
        @JvmStatic
        fun main(args: Array<String>): Unit {
            MyApp().launch(*args)
        }
    }
}

Similar tips are in these other related questions:

Community
  • 1
  • 1
Jayson Minard
  • 84,842
  • 38
  • 184
  • 227