Вопрос по java – Scala-геттеры и сеттеры в классе Java

11

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

Я попробовал следующий простой класс, но он не работает:

public class JavaA {
private int a = 0;

public int a() {
    return a;
}

public void a_$eq(int a) {
    this.a = a;
}
}

Но когда я пытаюсь получить доступ к нему из Scala:

val x = new JavaA
x.a = 1

и я получаю "переназначение на val" сообщение об ошибке. Я пытался найти это, но все проблемы, которые я нашел, где-то наоборот, от скалы до Java.

Как правильно это сделать?

Спасибо!

Я много работаю с EMF (model2model, преобразование model2text), поэтому я подумал, что сделаю код немного более элегантным с помощью функции = значение вместо setFeatute (значение). fikovnik

Ваш Ответ

2   ответа
1

ты не сможешь. В Scala метод доступа должен быть методом без списка параметров, напримерdef a = _a. Написание, напримерdef a() = _a в Scala вызовет ту же ошибку, и вы не сможете определить метод без списка параметров в Java. Вы можете обмануть компилятор Scala, сгенерировав собственныйScalaSignature, но это вряд ли стоит того ...

Проблема, однако, не в доступе.println(x.a) отлично работает (как иx.a_=(1)). Travis Brown
@ TravisBrown Это так, потому что синтаксический сахар работает только при наличии такого средства доступа согласно спецификации языка. Jean-Philippe Pellet
Ah! Вы правы. Как странно Travis Brown
Пример с Scala не совсем верный, потому что, как я помню,def a() = _a не определяет пустой список параметров, но тот, который принимает Unit. Не уверен, что это только внутренняя часть или она сохраняется в процессе компиляции, но я думаю, это так. kutschkem
@ kutschkem Ты не прав.def a() = … определяет пустой список параметров. Jean-Philippe Pellet
13

и это достаточно сложно, что ты, вероятно, не хочешь.

Что ты Не может do - это написать простой Java-класс, который магически интерпретируется как геттеры и сеттеры Scala. Причина в том, что Scala встраивает информацию в файл класса, который требуется для его методов получения и установки (например, есть ли блоки с нулевым параметром или один пустой блок параметра - различие, которое не сохраняется в JVM (или в Java)).

Что тыможе do - использовать Java для реализации определенного Scala-интерфейса (т. е. черта):

// GetSetA.scala
trait GetSetA { def a: Int; def a_=(a: Int): Unit }

// JavaUsesGSA.java
public class JavaUsesGSA implements GetSetA {
  private int a = 0;
  public int a() { return a; }
  public void a_$eq(int a) { this.a = a; }
}

Что ты Не может do, тем не менее, использует класс напрямую (опять же, потому что Java не добавляет соответствующую информацию аннотации для Scala):

scala> j.a = 5
<console>:8: error: reassignment to val
       j.a = 5

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

scala> (j: GetSetA).a = 5
(j: GetSetA).a: Int = 5

Так что это скорее смешанная сумка. Несовершенно, но в некоторых случаях может быть достаточно функциональным, чтобы помочь.

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

(Изменить: Конечно, нет критической причины, по которой компилятордолже действовать так; Можно утверждать, что интерпретация определенных парами getter / setter Java, как если бы они были Scala (т. е. если файл классов явно не говорит, что это из Scala), является хорошим кандидатом для улучшения возможностей для улучшения совместимости Java.)

Спасибо за понимание! Я беспокоился, что это не сработает. fikovnik
Ницца; классный трюк с реализованной чертой! Jean-Philippe Pellet

Похожие вопросы