Scala implicit parameter null when implicit val is determined after method call

Consider:

object implicitnull extends App {
  mymethod

  implicit val arg = "foo"

  def mymethod(implicit arg: String) = {
    arg.size
  }
}

This does not cause a compilation error, however at run time the result NullPointerExceptioncomes from arg.size.

Is this the intended behavior?

+4
source share
1 answer

Yes, this is the intended behavior because of the way Scala creates classes and initializes them. Consider this example:

scala> class A {
     |   f
     | 
     |   implicit val arg = "foo"
     | 
     |   def f(implicit arg: String) = {
     |     println(arg)
     |   }
     | }
defined class A

scala> class B {
     |   f(arg)
     | 
     |   val arg = "foo"
     | 
     |   def f(implicit arg: String) = {
     |     println(arg)
     |   }
     | }
defined class B

scala> class C {
     |   implicit val arg = "foo"
     | 
     |   f
     | 
     |   def f(implicit arg: String) = {
     |     println(arg)
     |   }
     | }
defined class C

scala> new A
null
res0: A = A@67d3caf

scala> new B
null
res1: B = B@3f2c5ad4

scala> new C
foo
res2: C = C@177bdd23

Currently, the function fis called in the class C, the value is initialized, and in the class Bit is not yet initialized. The class is Aexactly the same as the class B- the only difference is that Scala implicitly << 26> passes A.

, 2 - - . B, , val arg , f , . val arg = "foo" . Java, :

public class B {

    void f(String arg) {
        System.out.println(arg);
    }

    String arg; // also acts as final in Scala

    public B() {
        f(arg);
        arg = "foo";
    }
}

lazy val :

scala> class B {
     |   f(arg)
     | 
     |   lazy val arg = "foo"
     | 
     |   def f(implicit arg: String) = {
     |     println(arg)
     |   }
     | }
defined class B

scala> new B
foo
res3: B = B@3f9ac6e6
+9

Source: https://habr.com/ru/post/1530095/


All Articles