#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
.