Применить функцию к параметру метода

#scala #methods #implicit

Вопрос:

Мне нужно обновить поле в методе, который вызывается из многих мест. Я хочу, чтобы все значения, заданные в поле, были прописными. Но я не хочу преобразовывать его внутри методов, где это требуется. И не хочу создавать другую ценность. Я спрашиваю, могу ли я использовать тип импликаций для преобразования значения?

 def parent(itemType: String) =
   getValue(itemType.toUperCase)
 

или

 def parent(itemType: String) = 
   getValue(itemType)

getValue(itemType: String) = {
  val formattedValue = itemType.toUperCase
}
 

Я хочу избежать обоих подходов и попросить что-то вроде:

 getValue(itemType: String = itemType.toUperCase) = { 
   // use itemType as upercase value
}
 

Комментарии:

1. Что такое «поле в методе»?

2. Оба ваших подхода в порядке. Выбери одну. Если вам нужно вызвать как верхний корпус, так и оригинальный метод, сделайте обертку. Если нет `def foo(_i: Строка) = {val i = _i.Прописные буквы; …}

3. примените функцию к полю из определения метода: def getValue(itemType: String // here, I want to format the itemType to UperCase directly if it is possible)

4. Использование изменяемых значений и вызов метода «get» не является идиоматическим Scala. Используйте неизменяемый класс и преобразуйте значение в верхний регистр в конструкторе ( apply метод в сопутствующем объекте).

Ответ №1:

Лучше всего было бы воплотить прописные буквы в системе типов.

 import scala.language.implicitConversions

object Refined {
  class UppercaseString private[Refined](override val toString: String) extends AnyVal

  implicit def stringToUpper(s: String): UppercaseString = new UppercaseString(s.toUpperCase)

  implicit def upperToString(ucs: UppercaseString): String = ucs.toString
}
 

Затем вы можете выразить, что строка должна быть прописной (и прозрачно сделать обычную строку прописной) с помощью

 import Refined._

def getValue(itemType: UppercaseString) = ???
 

Наличие неявного преобразования в UppercaseString означает, что до тех пор, пока Refined.stringToUpper оно было импортировано, мы можем вызывать getValue произвольные строки.

Поскольку UppercaseString расширяется AnyVal , во многих случаях у него не будет накладных расходов за пределами строки в верхнем регистре. Поскольку это тип, вызывающий код может сохранять его как UppercaseString и сохранять вызовы toUpperCase .

Обратите внимание, что implicit class это здесь не работает, так как мы хотим выполнить операцию в процессе «построения»; конструктор UppercaseString предназначен private для Refined того, чтобы мы могли гарантировать, что все создание будет выполнено toUpperCase .