代码之家  ›  专栏  ›  技术社区  ›  Germán

懒洋洋地加载一些配置参数,试图在Scala中找到一个模式

  •  3
  • Germán  · 技术社区  · 16 年前

    我希望我的客户机代码看起来像这样:

        val config:Config = new MyConfig("c:/etc/myConfig.txt")
        println(config.param1)
        println(config.param2)        
        println(config.param3)
    

    也就是说:

    • Config接口定义配置字段
    • MyConfig是一个配置实现——所需的所有连接都是所需实现的实例化
    • 数据是延迟加载的——它应该发生在第一个字段引用上(配置参数1在这种情况下)

    到目前为止,我对自己的想法并不满意:

    trait Config {
      lazy val param1:String = resolveParam1
      lazy val param2:String = resolveParam2
      lazy val param3:Int = resolveParam3
    
      protected def resolveParam1:String
      protected def resolveParam2:String
      protected def resolveParam3:Int
    }
    
    class MyConfig(fileName:String) extends Config {
      lazy val data:Map[String, Any] = readConfig
    
      // some dummy impl here, should read from a file
      protected def readConfig:Map[String,Any] = Map[String, Any]("p1" -> "abc", "p2" -> "defgh", "p3" -> 43)
    
      protected def resolveParam1:String = data.get("p1").get.asInstanceOf[String]
      protected def resolveParam2:String = data.get("p2").get.asInstanceOf[String]
      protected def resolveParam3:Int = data.get("p3").get.asInstanceOf[Int]
    }
    

    我相信有更好的解决方案,这是您可以提供帮助的:)

    任何 ],我需要转换值。

    2 回复  |  直到 16 年前
        1
  •  1
  •   Daniel Spiewak    16 年前

    没有什么能阻止你把价值抽象化。您不能在super trait中强制执行惰性,但这没关系,因为惰性加载实际上是一个实现细节:

    trait Config {
      val param1: String
      val param2: String
      val param3: Int
    }
    
    class MyConfig extends Config {
      lazy val param1 = readConfig().("p1")
      ...
    
      def readConfig(): Map[String, String] = ...
    }
    

    从风格上来说, readConfig() 应该用parens(而不是不使用parens)声明和调用,因为这是一个副作用的方法。no-parens语法旨在表示纯函数方法。

        2
  •  0
  •   sblundy    16 年前

    trait Config {
      def param1:String
      def param2:String
      def param3:Int
    }
    
    class MyConfig(fileName:String) extends Config {
      lazy val data:Map[String, Any] = readConfig
    
      // some dummy impl here, should read from a file
      protected def readConfig:Map[String,Any] = 
        Map[String, Any]("p1" -> "abc", "p2" -> "defgh", "p3" -> 43)
    
      def param1:String = data.get("p1").get.asInstanceOf[String]
      def param2:String = data.get("p2").get.asInstanceOf[String]
      def param3:Int = data.get("p3").get.asInstanceOf[Int]
    }
    

    为了摆脱铸造,你可以 MyConfig 包装一个由 MyConfig公司 .

    class MyConfig(fileName:String) extends Config {
      private class NonLazyConfig(val p1:String, p2:String, p3:int) extends Config {
          def param1 = p1
          def param2 = p2
          def param1 = p3
      }
      lazy val inner:Config = readConfig
    
      // some dummy impl here, should read from a file
      protected def readConfig:Config = {
        return new NonLazyConfig("abc", "defgh", 43)
      }
      def param1:String = inner.param1
      def param2:String = inner.param2
      def param3:Int = inner.param3
    }