Почему вы не можете создать сеттер без геттера в scala?

Я нашел в Scala: не могу написать сеттер без геттера? что вы можете не создавать сеттер без геттера:

Интерпретация присвоения простой переменной x = e зависит от определения x. Если x обозначает изменяемую переменную, то присваивание изменяет текущее значение x на результат вычисления выражения e. Ожидается, что тип e будет соответствовать типу x. Если x является функцией без параметров, определенной в некотором шаблоне, и тот же шаблон содержит функцию установки x_= в качестве члена, то присваивание x = e интерпретируется как вызов x_=(e ) этой функции установки. Аналогично, присваивание fx = e функции без параметров x интерпретируется как вызов f.x_=(e ). Присваивание f(args) = e с применением функции слева от оператора ‘=’ интерпретируется как f.update(args, e ) , то есть вызов функции обновления, определенной f .

Таким образом, дизайнерское решение не разрешать сеттеры без геттеров. Но почему? Это просто сложнее реализовать или это невозможно сделать в принципе?

У меня есть правильный вариант использования для него, используя его в качестве (несколько сложного) сеттера, где неиспользование этого синтаксического сахара нарушило бы одинаковый синтаксис везде в проекте.


person Rik Schaaf    schedule 25.08.2016    source источник
comment
Вы можете объяснить ситуацию? Почему это проблема с геттером?   -  person Nathaniel Ford    schedule 25.08.2016
comment
@NathanielFord проблема в том, что это часть API, это может сбить пользователя с толку, думая, что можно использовать геттер. Ситуация: у объекта класса А есть сеттер, который устанавливает определенное значение. Объект класса B, который каким-то образом «подключен» к объекту класса A, может получить это значение, используя свой геттер с тем же именем. Думайте об этом как о двух устройствах с проводом между ними, где одно устройство имеет только выход, который является входом другого устройства: (в классе A) out.value = 3.0 и (в классе B) println(in.value )   -  person Rik Schaaf    schedule 25.08.2016
comment
@ coolcat007: В этом случае вам, вероятно, следует использовать явный метод установки вместо присваивания.   -  person Bergi    schedule 25.08.2016
comment
@ coolcat007 Что сказал Берги. Но также обратите внимание, что С.О. не умеет отвечать на вопросы «почему это так», а только на вопросы «что я могу сделать с тем фактом, что это именно так». В вашем случае кажется, что вы должны просто написать свой собственный сеттер для внутреннего скрытого значения. «Причина», по которой Scala делает вещи таким образом, заключается в том, что они хотят иметь возможность делать предположения в компиляторе, которые упрощают жизнь: парные геттеры и сеттеры делают это.   -  person Nathaniel Ford    schedule 25.08.2016
comment
@NathanielFord Я думаю, что на данный момент Scala работает так, что действительно лучше создать явный установщик, хотя, на мой взгляд, это выглядит некрасиво в коде, поскольку одна из причин использования Scala заключается в том, что я не Не нужно использовать слово «набор» в каждом сеттере. Я просматривал исходный код компилятора scala, но не смог найти, где реализовано преобразование _=. Это где-то в пакете nsc.transform или я ищу не в том месте?   -  person Rik Schaaf    schedule 25.08.2016
comment
@ coolcat007 преобразование запускается при проверке типа присваивания, см. typedAssign и normalTypedApply. Смотрите мой ответ, что это не просто переписывание синтаксиса, если это полезное различие.   -  person som-snytt    schedule 25.08.2016
comment
@NathanielFord согласен с вами, что вопрос не подходит для форума.   -  person som-snytt    schedule 25.08.2016


Ответы (1)


Вы можете попробовать это, чтобы исключить аксессор из вашего API:

scala> class C { def c_=(i: Int) = println(i) ; private def c: Int = ??? }
defined class C

scala> val c = new C
c: C = C@289fdb08

scala> c.c = 42
<console>:14: error: method c in class C cannot be accessed in C
val $ires0 = c.c
               ^
<console>:12: error: method c in class C cannot be accessed in C
       c.c = 42
         ^

scala> def f = { c.c = 42 ; 0 }
<console>:12: error: method c in class C cannot be accessed in C
       def f = { c.c = 42 ; 0 }
                   ^

В первой ошибке REPL пытается сообщить значение с помощью метода доступа.

Это понятие парного средства доступа и мутатора называется принципом универсального доступа, так что член, к которому осуществляется доступ, выглядит как свойство.

Выражение c.c должно пройти проверку типов перед дальнейшей дешугаризацией. В противном случае преобразование (к вызову c.c_=) должно быть чисто синтаксическим.

Например, в игру может вступить неявное преобразование, предоставляющее метод расширения c_=.

person som-snytt    schedule 25.08.2016
comment
Меня немного смущают последние два абзаца вашего ответа. Что именно ты имеешь ввиду? - person Rik Schaaf; 25.08.2016
comment
Просто c.c должно что-то означать само по себе. Если вы сказали, что c.c = просто означает c.c_=, то неявное преобразование может добавить мутатор c_=. Это далеко от простого свойства. - person som-snytt; 25.08.2016
comment
Рассмотрим pastebin.com/yxsmumG3 (да, я знаю, что-то соль...) это может быть не простое свойство, но его использование вполне понятно, и видно, что геттер password никогда не будет использоваться, в то время как password_= составляет половину основной части этого примера. Я мог бы переименовать password_= в setPassword и явно вызвать этот метод, но тогда мы вернулись бы к тому, что было при использовании старой доброй Java. Если оставить средство получения паролей, это запутает любого, кто использует API. - person Rik Schaaf; 25.08.2016
comment
Думаю, мой аргумент о том, что такое property, не был убедительным. Но если вопрос в том, что вы должны делать вместо этого, то экосистема изобилует операторами присваивания, которые представляют собой операции, оканчивающиеся на =. Таким образом, вы могли бы password ~= "secret", где тильда напоминает вам, что перед установкой значения применяется хеш-фраза. См. различные операции в sbt, <++= и т. д. по адресу scala-sbt.org/0.13.12/api/index.html#index.index-_ - person som-snytt; 25.08.2016
comment
Хорошо, не обращайте внимания на мой последний комментарий: twitter.com/eed3si9n/status/769029653700968448 - person som-snytt; 26.08.2016