Feature suggestion: allow non-static inner classes to be subcommands of their outer class
See original GitHub issueFor example, something like (not tested)
@Command(name="outer", subcommands={Inner.class})
public class Outer {
@Command(name="inner")
public class Inner {}
}
Currently this doesn’t work, since Inner
requires an instance of Outer
. Would it be possible to make it so that when an instance of Outer
is run via the CommandLine
it will create an instance of Inner
and use it as a subcommand? This would probably only really work if Inner
is a subcommand of Outer
, as opposed to a subcommand of a completely separate class.
I know Inner
could be made static, but then it loses the ability to use private variables of Outer
, which is useful. Another possible way to do something like this (which I have not tested) might be to use a method as the command and have it run a new Inner
object with all args it recieves. But even if that would work (and I’m not sure), it would be simpler to be able to be able to just put it in the subcommands
section.
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (4 by maintainers)
That makes sense, fair enough.
I’ve given it some thought (thanks for the PR in #621 that made it very concrete what you had in mind) but I’m leaning against doing this, for three reasons.
There is an alternative
You can use a static inner class and still access the private variables of the outer class, using the
@ParentCommand
annotation:Making
InnerClassFactory
the default factory would not always workFor example, there are the static methods like the below, where a class is passed in, and there is no instance of the outer class available. Non-static inner class commands would work with other API calls but would result in runtime exceptions with these methods. This would surprise some users which we should avoid.
There may be other edge cases where
InnerClassFactory
does not work, I haven’t looked in detail. I imagine there may be a problem if command hierarchy has several levels of non-static inner class commands: we pass in an instance of the top-most class, but another instance would be needed for the class that is nested inside the inner class…I prefer to keep the contract of
IFactory
simpleIf the default implementation can handle non-static inner classes then in practice users will expect that capability from all factory implementations. I think this is demanding too much for other implementors.
The factory is mainly intended for integration with dependency injection frameworks like Micronaut or Spring Boot, where the DI framework is responsible for creating instances (which themselves may have services injected into them by the DI framework).
The current default factory is straightforward and can easily be replaced by one that integrates with the dependency injection framework, see for example the Guice example from the picocli documentation.
If we replaced the current simple default factory with a more powerful one that also handles inner classes, that would make integration with dependency injection frameworks more difficult which would defeat the purpose.