Scala:在不创建对象的情况下获取默认值

Posted

技术标签:

【中文标题】Scala:在不创建对象的情况下获取默认值【英文标题】:Scala: get default values without creating an object 【发布时间】:2016-03-13 15:36:06 【问题描述】:

假设构造函数中有一个具有默认值的类:

class Adapter(url: String = "127.0.0.1", port: Int = 8080)

是否可以在运行时获取这些参数的默认值而不创建此对象的实例?

请不要询问用例,这更多是关于语言本身的问题。

【问题讨论】:

【参考方案1】:

将它们移动到伴随对象中?

case class Adapter(url: String = Adapter.defaultURL, port: Int = Adapter.defaultPort)

object Adapter 
    val defaultURL = "127.0.0.1"
    val defaultPort = 8080

如果只能从 case class 访问默认值,则可以使用 private 限定更多默认值

【讨论】:

这不是 OP 的这个问题的答案 这似乎是一个不错的答案。我不明白这个问题。如果问题是示例代码中的硬编码值,您可以轻松地想象一个 "def lookupAdapterUrl" 而不是 "val defaultURL" 。 . . . 您将如何以编程方式发现它们?【参考方案2】:

我假设您最感兴趣的是默认方法是如何在内部实现的。这是您的代码的 javap 反汇编(使用非常有用的 :javap <classname> scala 控制台命令:

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       

  ...

如您所见,创建默认值的方法在伴随对象中被编码为特殊命名的方法。因此,要在不重构示例的情况下调用这些方法,您必须使用反射:

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

显然,在生产代码中这样做可能不是一个好主意,因为名称修改细节等可能会改变。在这种情况下,只需使用@Sparko 的建议即可。

关于名称修改方案的说明:该方案是methodName + "$default$" + parameterNumber。上例中要修饰的方法是构造函数,即“”。所以你最终得到例如"$lessinit$greater" 为方法名,"$lessinit$greater$default$0" 为方法名,用于计算第一个参数的默认值。

【讨论】:

以上是关于Scala:在不创建对象的情况下获取默认值的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不调用新活动的情况下获取对象值?

Groovy - 如何在不更新地图的情况下使用默认值获取地图值

C#在不创建实例的情况下获取属性值?

在不调用构造函数的情况下创建 Vector 元素

Scala:如何使用默认值初始化对象

如何在不创建查询的情况下从 Access 表中获取值