Может ли ссылаться на член объекта до того, как я его создаю? - PullRequest
2 голосов
/ 05 февраля 2011

Вот что я хочу сделать (предупреждение: впереди чрезвычайно сломанный Scala):

def assignToFour[X](x : X, y : Something[X]) =  x.y = 4

class M {
   var m = 0;
}

val em = new M
assignToFour(em, M.m)
em.m == 4

Очевидно, что это не сработает, но я ищушаблон, который позволит мне ссылаться на член экземпляра в аннотации, а затем на более позднем этапе получить доступ к этому члену на фактическом экземпляре.

Если бы это был Java, я бы использовал отражение, но отражение отстойи я надеюсь, что у Scala, которая отстой намного меньше, чем у Java, будет лучшая альтернатива.

Ответы [ 3 ]

4 голосов
/ 05 февраля 2011

Итак:

  • Свойства Scala реализованы в виде пары методов. Для var m метод получения будет иметь имя m, а метод установки - m_=
  • Методы могут быть автоматически подняты к функциям
  • Функции могут передаваться как первоклассные значения

Начиная здесь:

class M {
  var m = 0
}

val x = new M

x.m в настоящее время 0, давайте изменим это ... Вот метод, который принимает функцию в качестве аргумента и вызывает эту функцию со значением 4:

def callWithFour(fn: Int=>Unit) = fn(4)

И используя его:

callWithFour(x.m_=)

Где x.m_= - метод установки для свойства m в экземпляре x

x.m теперь равно четырем.

3 голосов
/ 05 февраля 2011

Хотя структурные типы являются альтернативой, они используют внутреннее отражение.

Что вы на самом деле хотите сделать, так это вызвать установщик некоторого свойства, чтобы вы могли обобщить его до вызова функции:

def applyWith4[X,Y](x: X)(f: X => Int => Y) = f(x)(4)

Этот метод принимает два аргумента: некоторый экземпляр X и одну функцию f, которая превращает ваш X в функцию из Int в некоторый тип Y (в вашем случае это будет Unit ).

Теперь вы можете вызвать его, используя

applyWith4(em)(x => x.m = _)

или в более коротком, но менее читаемом варианте с использованием сгенерированного установщика m_=:

applyWith4(em)(_ m_=)
1 голос
/ 05 февраля 2011

Вы можете использовать structural types, так что вы не будете зависеть от конкретного типа (хотя и потеряете некоторую гибкость, не имея возможности передать имя свойства для обновления):

def assignToFour(x:{var y:Int}) = x.y = 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...