Why val class parameter cannot be called?

I am trying to use a class to combine a bunch of proxies for API functions as a single interface. Several of them are null functions, but I do not want their inclusion in the class constructor to cause API calls. My solution right now is to wrap the call in a literal null function new myClass(() => apiCall), and then explicitly call the member function. This is not so bad, but I wonder if there is a technical reason why I cannot just use the call-by-name parameter to pass a lazy reference to this method?

Example:

scala> class MyClass(val apiCall: => String)
<console>:1: error: `val' parameters may not be call-by-name
       class MyClass(val apiCall: => String)

Change . I should have pointed out that my question is why the class cannot have a parameter val. Added example.

+4
source share
1 answer

A class can very well have default parameters if they are not valor var:

> scala
Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class Foo(f: => Unit) {
     |   def run(): Unit = f
     | }
defined class Foo

scala> new Foo(println("hello"))
res0: Foo = Foo@5da6b8c6

scala> res0.run()
hello

The reason why a parameter valor varcannot be by name is simply because the class field cannot be by name, no more than a local variable, for that matter. Therefore, the following is not permissible:

scala> class FooInvalid(val v: => Unit) {
<console>:1: error: `val' parameters may not be call-by-name
       class FooInvalid(val v: => Unit) {
                               ^

However, it is possible to have a by-name parameter that is assigned as a function for a field vallike this (but then you should use it ()as the call site):

scala> class FooVal(v0: => Unit) {
     |   val v: () => Unit = () => v0
     | }
defined class FooVal

scala> new FooVal(println("hello"))
res2: FooVal = FooVal@75c145bc

scala> res2.v
res3: () => Unit = <function0>

scala> res2.v()
hello

Finally, instead of defining vas a valtype () => Unit, you can define it as a deftype Unit. And then you get the behavior that you probably want in the first place:

scala> class FooDef(v0: => Unit) {
     |   def v: Unit = v0
     | }
defined class FooDef

scala> new FooDef(println("hello"))
res5: FooDef = FooDef@2e04a041

scala> res5.v
hello

, , , a val (, import x._ , ), a def ( ()) . , .

+5

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


All Articles