具有隐式 Class Scala 的特征

Traits With implicit Class Scala

以我为例。我想找到一种在与 aws-sns 的连接中使用隐式值的方法。

object SNSClient {

}

class SNSClient {
  val region =
    try {
      val prop = new Properties()
      prop.load(new FileInputStream("config.properties"))
      prop.getProperty("aws.region")
    } catch {
      case e: Exception => println("error")
    }

 // In this method Scala wont compile
 def providesSNSClient(): AmazonSNS = {
      AmazonSNSClientBuilder
             .standard
             .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey.toString(), secretKey.toString())))
             .withRegion(region) //Error compile
             .build()
  }
}

 /**
  * Rich prpierties
  */
 trait RegionsImplict {
   /**
    * Return default value if it does not provide Regions.EU_WEST_1
    */
   implicit class RegionB(region: String){
     def asRegion: Regions = Regions.values().find(_.name == region).getOrElse(Regions.EU_WEST_1)
   }

 }

到目前为止一切顺利,我想在我的行代码中调用我的函数 asRegion .withRegion(region)//错误编译

这里的问题是 region 不是 String,所以隐式转换不会启动。

您可以通过以下简化的 Scala REPL 示例看到这一点:

scala> val region = try { "value" } catch { case e: Exception => println("error") }
region: Any = value  // <--- notice type is Any

为什么?因为一些代码路径(即 catch 短语)不产生字符串,所以编译器必须 "settle" 最接近的公共超类型,即 Any.

要解决这个问题,您应该在出现异常时中止,或者提供一些默认值,否则某些代码路径根本不会生成字符串。例如:

val region =
  try {
    val prop = new Properties()
    prop.load(new FileInputStream("config.properties"))
    prop.getProperty("aws.region")
  } catch {
    case e: Exception => println("error"); "us-east" // Default!
  }  

注意:如评论所述,不建议如此轻率地使用隐式转换,尤其是对于常见类型,例如字符串 - 他们可能会在您不希望它们出现时出现,并使代码更难阅读。