加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala中的惰性val和隐式参数

发布时间:2020-12-16 08:52:24 所属栏目:安全 来源:网络整理
导读:我一直试图了解隐式参数在 Scala中的工作原理.据我所知,隐式参数解析如下: 将对象显式传递给方法. 范围中定义的隐式定义. 用作隐式参数的类的伴随对象 然而,当我开始玩这个懒惰的vals时,我得到了一些帮助.懒惰的val似乎只使用最后的解析规则.以下是一些示例
我一直试图了解隐式参数在 Scala中的工作原理.据我所知,隐式参数解析如下:

>将对象显式传递给方法.
>范围中定义的隐式定义.
>用作隐式参数的类的伴随对象

然而,当我开始玩这个懒惰的vals时,我得到了一些帮助.懒惰的val似乎只使用最后的解析规则.以下是一些示例代码:

class Bar(val name:String)
object Bar { implicit def bar = new Bar("some default bar") }

class Foo {
  lazy val list = initialize
  def initialize(implicit f:Bar) = {
    println("initialize called with Bar: '" + f.name + "' ...")
    List[Int]()
  }
}

trait NonDefaultBar extends Foo {
  implicit def f = new Bar("mixed in implicit bar")
  def mixedInInit = initialize
  lazy val mixedInList = list
}

object Test {
    def test = {
      println("Case 1: with implicitp parameter from companion object")
      val foo1 = new Foo
      foo1.list
      foo1.initialize

      println("Case 2: with mixedin implicit parameter overriding the default one...")
      val foo2 = new Foo with NonDefaultBar 
      foo2.mixedInList

      val foo3 = new Foo with NonDefaultBar 
      foo3.mixedInInit

      println("Case 3: with local implicit parameter overriding the default one...")
      implicit def nonDefaultBar = new Bar("locally scoped implicit bar")
      val foo4 = new Foo 
      foo4.list
      foo4.initialize
    }
}

调用Test.test给出以下输出:

Case 1: with implicitp parameter from companion object 
initialize called with Bar: 'some default bar' ... 
initialize called with Bar: 'some default bar' ... 
Case 2: with mixedin implicit parameter overriding the default one... 
initialize called with Bar: 'some default bar' ... 
initialize called with Bar: 'mixed in implicit bar'... 
Case 3: with local implicit parameter overriding the default one... 
initialize called with Bar: 'some default bar' ... 
initialize called with Bar: 'locally scoped implicit bar' ...

为什么编译器在第2种情况下调用mixedInList时没有发现有混合条件.在案例3中,它在访问列表时也错过了本地定义的隐式Bar.

是否有任何方法可以使用隐式val的隐式参数,而不使用随播对象中定义的隐式?

解决方法

这是因为当编译器编译Foo类时,没有其他隐式Bar. Java中的反编译代码如下所示:

public class Foo
  implements ScalaObject
{
  private List<Object> list;
  public volatile int bitmap$0;

  public List<Object> list()
  {
    if (
      (this.bitmap$0 & 0x1) == 0);
    synchronized (this)
    {
      if (
        (this.bitmap$0 & 0x1) == 0) {
        this.list = initialize(Bar..MODULE$.bar()); this.bitmap$0 |= 1; } return this.list;
    }
  }
  public List<Object> initialize(Bar f) { Predef..MODULE$.println(new StringBuilder().append("initialize called with Bar: '").append(f.name()).append("' ...").toString());
    return Nil..MODULE$;
  }
}

延迟val只是一种方法,它检查变量是否已经设置并返回它,或者设置它然后返回它.所以你的mixin根本没有被考虑在内.如果你想要,你必须自己处理初始化.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读