7.8. Parametry przekazywane przez nazwę

Parametry metod w Scali mogą być przekazywane przez wartość lub przez nazwę. Dotychczas używane w tym rozdziale parametry były przekazywane przez wartość. W przypadku takiego parametru wartość argumentu w wywołaniu metody jest obliczana przed wywołaniem samej metody.

Parametr metody greet1, zdefiniowanej w pliku ByNameParameters1.scala, jest przekazywany przez wartość. Wobec tego jego ewaluacja następuje przed wywołaniem samej metody.

Plik ByNameParameters1.scala:
def greet1(greeting: String) {
  println("in greet")
  println(greeting + "!")
}

W pliku ByNameParameters2.scala zdefiniowana jest metoda hello, która zwraca łańcuch znaków, wcześniej wyświetlając komunikat na ekranie. Ta metoda posłuży do zilustrowania użycia parametrów przekazywanych przez wartość i przez nazwę.

Plik ByNameParameters2.scala:
def hello:String = {
  println("in hello")
  "hello"
}

W poniższym przykładzie najpierw wykonana zostaje metoda hello obliczająca argument metody greet1, a dopiero potem wywołana zostaje metoda greet1.

scala> :load ByNameParameters1.scala
Loading ByNameParameters1.scala...
greet1: (greeting: String)Unit

scala> :load ByNameParameters2.scala
Loading ByNameParameters2.scala...
hello: String

scala> greet1(hello)
in hello
in greet
hello!

Jeśli chcemy, aby wartość parametru była przekazywana przez nazwę, to między znakiem dwukropka, a specyfikacją typu parametru należy umieścić podwójną strzałkę w prawo (czyli znaki => lub znak ). Parametry przekazywane przez nazwę są ewaluowane dopiero w momencie odwołania się do nich wewnątrz metody. Metoda greet3, zdefiniowana w pliku ByNameParameters3.scala, zawiera deklarację parametru przekazywanego przez nazwę.

Plik ByNameParameters3.scala:
def greet3(greeting: => String) {
  println("in greet")
  println(greeting + "!")
}

W poniższym przykładzie wywołanie metody hello następuje dopiero po wywołaniu metody greet3, w momencie, w którym w tej metodzie następuje odwołanie do przekazanego przez nazwę parametru greeting.

scala> :load ByNameParameters3.scala
Loading ByNameParameters3.scala...
greet3: (greeting: => String)Unit

scala> greet3(hello)
in greet
in hello
hello!

Ewaluacja argumentu przekazanego przez nazwę następuje przy każdym odwołaniu do parametru w ciele metody. W zdefiniowanej w pliku ByNameParameters4.scala metodzie o nazwie greet4 odwołanie do parametru greeting występuje dwukrotnie.

Plik ByNameParameters4.scala:
def greet4(greeting: => String) {
  println("in greet");
  println(greeting + "!")
  println(greeting + "!!")
}

Wykonanie poniższego wyrażenia skutkuje dwukrotnym wywołaniem metody hello.

scala> :load ByNameParameters4.scala
Loading ByNameParameters4.scala...
greet4: (greeting: => String)Unit

scala> greet4(hello)
in greet
in hello
hello!
in hello
hello!!

Ewaluacja argumentu przekazanego przez nazwę może w ogóle nie nastąpić. Skoro ewaluacja argumentu przekazanego przez nazwę występuje przy każdym odwołaniu do parametru w ciele metody, to jeśli takie odwołanie nie nastąpi, argument nie będzie w ogóle obliczony. Metoda zdefiniowana w pliku ByNameParameters5.scala, w zależności od wartości logicznej przekazanej w pierwszym parametrze, wykonuje kod przekazany albo w drugim, albo w trzecim parametrze.

Plik ByNameParameters5.scala:
def ifelse(cond: Boolean, ifblock: => Unit, elseblock: => Unit) =
  if (cond) ifblock else elseblock

Przykładowe wywołania tej metody pokazują, że metoda wywołuje jeden z dwóch przekazanych jej bloków kodu, a drugi pozostaje niewywołany.

scala> :load ByNameParameters5.scala
Loading ByNameParameters5.scala...
ifelse: (cond: Boolean, ifblock: => Unit, elseblock: => Unit)Unit

scala> var sayHello = true
sayHello: Boolean = true

scala> ifelse(sayHello, println("Hello"), println("Hi"))
Hello

scala> sayHello = false
sayHello: Boolean = false

scala> ifelse(sayHello, println("Hello"), println("Hi"))
Hi

Specyfikacja języka Scala opisuje parametry przekazywane przez nazwę w punkcie 4.6.2.

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.