Редактировать: ошибка, вызвавшая этот вопрос , была исправлена .
В справочнике Scala я могу прочитать (стр. 86):
Интерпретация присваивания простой переменной x = e зависит от определения x.Если x обозначает непостоянную переменную, то присваивание изменяет текущее значение x на результат вычисления выражения e.Ожидается, что тип e будет соответствовать типу x.Если x - это функция без параметров, определенная в некотором шаблоне, и тот же шаблон содержит функцию-установщик x_ = в качестве члена, тогда присваивание x = e интерпретируется как вызов x _ = (e) этой функции-установщика.Аналогично, назначение f .x = e для функции без параметров x интерпретируется как вызов f.x _ = (e).
Так, например, что-то вроде этого работает нормально:
class A {
private var _a = 0
def a = _a
def a_=(a: Int) = _a = a
}
Затем я могу написать
val a = new A
a.a = 10
Но если я определю класс следующим образом, добавив параметр типа к методу a:
class A {
private var _a = 0
def a[T] = _a
def a_=(a: Int) = _a = a
}
, он не будетработать больше;Я получаю error: reassignment to val
, если я пишу a.a = 10
.Как ни странно, он по-прежнему работает без параметра типа и списка неявных параметров, например.
Возможно, в этом примере параметр типа не очень полезен, но при проектировании DSL было бы здоровочтобы метод метода вызывался, даже если метод имеет параметры типа (и, между прочим, добавление параметров типа в метод разрешено и работает нормально).
Итак, у меня три вопроса:
- Есть ли обходной путь?
- Следует ли считать текущее поведение ошибкой?
- Почему компилятор принудительно применяет метод получения, позволяющий использовать синтаксический сахар для метода установки?
ОБНОВЛЕНИЕ
Вот что я действительно пытаюсь сделать.Это довольно долго, извините, я хотел избежать этого, но понял, что опускать его было бы более запутанно.
Я проектирую GUI с SWT в Scala и получаю огромное удовольствие от использования XScalaWT Дэйва Орма , что значительно уменьшает объем необходимого кода.Вот пример из его сообщения в блоге о том, как создать SWT Composite
, который конвертирует ° C в ° F градусов:
var fahrenheit: Text = null
var celsius: Text = null
composite(
_.setLayout(new GridLayout(2, true)),
label("Fahrenheit"),
label("Celsius"),
text(fahrenheit = _),
text(celsius = _),
button(
"Fahrenheit => Celsius",
{e : SelectionEvent => celcius.setText((5.0/9.0) * (fahrenheit - 32)) }
),
button(
"Celsius -> Fahrenheit",
{e : SelectionEvent => fahrenheit.setText((9.0/5.0) * celsius + 32) })
)
)
Аргумент для каждого из методов создания виджетов имеет тип (WidgetType => Any)*
с несколькими полезными неявными преобразованиями, которые, например, позволяют напрямую указывать строку для виджетов, имеющих метод setText()
.Все функции конструктора импортируются из одноэлементного объекта.
В конце я хотел бы написать что-то вроде этого:
val fieldEditable = new WritableValue // observable value
composite(
textField(
editable <=> fieldEditable,
editable = false
),
checkbox(
caption = "Editable",
selection <=> fieldEditable
)
)
Это связало бы редактируемое свойствотекстовое поле для выбора флажка через переменную WritableValue.
Первое: именованные аргументы здесь не применимы, поэтому строка editable = false
должна откуда-то приходить.Итак, наряду с методами конструирования виджетов в объекте-одиночке я мог бы написать концептуально:
def editable_=[T <: HasEditable](value: Boolean) = (subject: T) => subject.setEditable(value)
... но это работает, только если есть и геттер.Отлично: мне все равно нужен геттер для реализации привязки данных с помощью <=>.Примерно так:
def editable[T <: HasEditable] = new BindingMaker((widget: T) => SWTObservables.observeEditable(widget))
Если бы это сработало, жизнь была бы хорошей, потому что я могу определить <=> в BindingMaker и использовать этот приятный синтаксис.Но, увы, параметр типа на получателе нарушает установщик.Отсюда мой первоначальный вопрос: почему этот простой параметр типа влияет на то, решит ли компилятор продолжить использование синтаксического сахара для вызова метода установки?
Надеюсь, теперь это станет понятнее.Спасибо за чтение…