Scala: перегрузка method\operator

Следующий пример из книги, 'Программирующей в Scala'. Учитывая класс 'Рациональный' и следующее определение метода:

def add(that: Rational): Rational =
    new Rational(
        this.numer * that.denom + that.numer * this.denom,
        this.denom * that.denom
    )

Я могу успешно перегрузить добавить метод с версией удобства, которая берет Международный аргумент и использует определение выше:

def add(that: Int): Rational =
    add(new Rational(that, 1))

Никакие проблемы до сих пор.

Теперь, если я изменяю имя метода на имя стиля оператора:

def +(that: Rational): Rational =
    new Rational(
        this.numer * that.denom + that.numer * this.denom,
        this.denom * that.denom
    )

И перегрузка как так:

def +(that: Int): Rational =
    +(new Rational(that, 1))

Я получаю следующую ошибку компиляции:

(fragment of Rational.scala):19: error: value unary_+ is not a member of this.Rational
+(new Rational(that, 1))
 ^

Почему компилятор ищет унарную версию + метод?

34
задан Peter Mortensen 28 April 2013 в 20:41
поделиться

3 ответа

В Scala любая конструкция типа + x , -x , ~ x и ! X преобразуется в вызов метода x.unary _ + и т. д. Это частично позволяет разрешить Java-подобный синтаксис наличия ! b в качестве отрицания логического b или -x как отрицание числа x .

Таким образом, фрагмент кода + (new Rational (that, 1)) транслируется в (new Rational (that, 1)). Unary _ + и как ] Rational не имеет этого метода, вы получите ошибку компиляции. Вы получите эту ошибку, только если ваша функция называется + , - , ~ или ! , поскольку это единственные символы, которые Scala допускает в качестве унарных операторов. Например, если вы вызвали свою функцию @ + , код компилируется нормально.

Тем не менее, я бы посоветовал написать переопределенную функцию добавления как:

def +(that: Int): Rational =
  this + (new Rational(that, 1))

Этот код лучше показывает назначение вашей функции - вы добавляете новый Rational , построенный из целого числа в качестве числителя и ] 1 как знаменатель для это . Этот способ записи переводится в this. + (New Rational (that, 1)) , что и нужно вам - вызов функции + на this ].

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

def add(that: Int): Rational =
  this add (new Rational(that, 1))
51
ответ дан 27 November 2019 в 16:47
поделиться

Если вызвать + с явным этим, то должно работать

def +(that: Int): Rational = this.+(new Rational(that, 1))

Scala позволяет определить одинарные операторы, которые могут быть использованы в префиксной нотации оператора. Например, можно использовать + в качестве префиксного оператора для достижения того же самого:

def unary_+: Rational = this.+(new Rational(that, 1))
val a = new Rational(3,2)
val b = +a

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

.
6
ответ дан 27 November 2019 в 16:47
поделиться

Вы не указали двоичный оператор +, вы указали унарный оператор +.

Итак, вместо:

def +(that: Int): Rational =
  +(new Rational(that, 1))

Надо написать следующее:

def +(that: Int): Rational =
  this +(new Rational(that, 1))
3
ответ дан 27 November 2019 в 16:47
поделиться
Другие вопросы по тегам:

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