Reputation: 4385
Suppose there is a class with default values in constructor:
class Adapter(url: String = "127.0.0.1", port: Int = 8080)
Is it possible to get default values for those parameters in runtime without creating an instance of this object?
Please do not ask about a use-case, this is more a question about the language itself.
Upvotes: 4
Views: 589
Reputation: 12565
I am assuming that you are mostly interested in how default methods are implemented internally. Here is the javap disassembly of your code (using the very helpful :javap <classname>
scala console command:
scala> class Adapter(url: String = "127.0.0.1", port: Int = 8080)
defined class Adapter
scala> :javap -c Adapter$ // Adapter$ because we want the companion object
Compiled from "<console>"
public class Adapter$ {
...
public java.lang.String $lessinit$greater$default$1();
Code:
0: ldc #16 // String 127.0.0.1
2: areturn
public int $lessinit$greater$default$2();
Code:
0: sipush 8080
3: ireturn
...
As you can see, the methods that create the default values are encoded as specially named methods in the companion object. So to invoke these methods without restructuring the example, you would have to use reflection:
scala> Adapter.getClass.getMethod("$lessinit$greater$default$1").invoke(Adapter)
res8: Object = 127.0.0.1
scala> Adapter.getClass.getMethod("$lessinit$greater$default$2").invoke(Adapter)
res9: Object = 8080
Obviously it is probably not a good idea to do this in production code, since the name mangling details etc. might change. Just use the suggestion from @Sparko in that case.
A note about the name mangling scheme: The scheme is methodName + "$default$" + parameterNumber
. The method to be decorated in the case above is the constructor, which is "<init>". So you end up with e.g. "$lessinit$greater" for the method name and "$lessinit$greater$default$0" for the name of the method to calculate the default value of the first argument.
Upvotes: 6
Reputation: 735
Move them into a companion object?
case class Adapter(url: String = Adapter.defaultURL, port: Int = Adapter.defaultPort)
object Adapter {
val defaultURL = "127.0.0.1"
val defaultPort = 8080
}
You can scope further default values with private
if they should only be accessible from the case class
Upvotes: 2