2012-06-05 2 views
11

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

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

public class JavaA { 
private int a = 0; 

public int a() { 
    return a; 
} 

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

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

val x = new JavaA 
x.a = 1 

и я получаю «переназначение ВАЛ» сообщение об ошибке , Я попытался найти это, но все проблемы, которые я нашел, где другой путь от scala до java.

Каков правильный путь?

Спасибо!

+0

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

ответ

13

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

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

Что вы можете сделать, это использовать 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; } 
} 

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

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

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

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

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

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

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

+0

Спасибо за понимание! Я беспокоился, что это не сработает. – fikovnik

+0

Nice; классный трюк с реализованной чертой! –

1

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

+1

Проблема не в аксессуаре. 'println (x.a)' работает просто отлично (как и 'x.a _ = (1)'). –

+1

@TravisBrown Это потому, что синтаксический сахар работает только в том случае, если есть такой аксессор, согласно спецификации языка. –

+0

Ах! Ты прав. Как странно. –

 Смежные вопросы

  • Нет связанных вопросов^_^