#scala
#scala
Вопрос:
У меня есть класс, подобный этому:
class A(arg: Int)(implicit i: Boolean) {
def apply(v: Double): this.type = {
// do stuff
this
}
}
и я хочу создать его экземпляр, инициализировав его и вызвав apply в одной строке:
implicit val i = false
val a = A(arg=1)(v=2.0) // doesn't work
val a2 = (A(arg=1))(v=2.0) // doesn't work
К сожалению, компилятор предполагает, что v = 2.0 предназначено для неявного параметра, а не для apply(). Я перепробовал несколько разных синтаксисов с помощью inserting {}’s и () ‘s, но ни один из них не сработал. Я понимаю, что v можно было бы переместить в конструктор, но в моем случае это не вариант, потому что A является подклассом, и я не хочу добавлять v в каждый конструктор подкласса. Есть ли способ добиться этого? Спасибо.
Комментарии:
1. @pst пробовал это, по какой-то причине не работает
2.
A(1)|>(_(2.0))
… ну, наверное, не лучше.
Ответ №1:
Как насчет «некрасиво, но, кажется, работает»…
class A(arg: Int)(implicit i: Boolean) {
def apply(v: Double): this.type = this
}
implicit val i = false
// removing the :A makes this fail to run on simplyscala
val a1 = (new A(arg=1) : A)(v=2.0)
// also works with explicit method name
val a2 = new A(arg=1).apply(v=2.0)
// and works without implicit being ... implicitized
val a = new A(arg=1)(i)(v=2.0)
Честно говоря, понятия не имею 🙂 Однако рассмотрите это, что может дать некоторое представление:
val a = (new A(arg=1))(2.0)
ошибка: несоответствие типов; найдено: Double(2.0) требуется: логическое значение значение a = (new A(arg=1))(2.0)
Вау!
Удачного кодирования.
Ответ №2:
(Я предполагаю, что у вас есть метод конструктора в сопутствующем объекте, поскольку вы его не используете new A
.)
Один из вариантов — записать его в двух строках:
val atmp = A(1)
val a = atmp(2.0)
… но это, конечно, не то, что вам нужно. Другим не менее неудовлетворительным вариантом было бы
val a = A(1)(implicitly)(2.0)
если вы можете с этим смириться. Возможно, наименее уродливый способ сделать это — вызвать apply
явно:
val a = A(1).apply(2.0)
Наконец, вы могли бы добавить новый метод конструктора к сопутствующему объекту, который позаботится обо всем:
object A {
def apply(arg: Int, v: Double)(implicit i: Boolean) = A(arg)(i)(v)
}
val a = A(1, 2.0)
Комментарии:
1. Мне нравится вариант 2, потому что он немного более явный, чем
apply
, и поскольку любой подход является более явным…