Класс Scala с частным конструктором и неявным параметром

Я хотел бы добавить неявный параметр в класс с частным конструктором. Вот как упрощенный пример:

class A[T] private(a:Int){ 
  def this()=this(0)
}

Если бы я хотел применить шаблон Pimp my library к T с помощью Ordered[T], мне нужно было бы использовать (устаревшее) представление, связанное следующим образом:

class A[T <% Ordered[T]] private(a:Int){ 
  def this()=this(0)
}

И это работает. Однако, чтобы избежать устаревшего синтаксического сахара, я хотел бы передать неявный параметр классу. К сожалению, здесь я, вероятно, делаю что-то не так:

class A[T] private(a:Int)(implicit conv:T=>Ordered[T]){ 
  def this()=this(0)
}

Для приведенного выше кода компилятор выдает следующую ошибку:

error: No implicit view available from T => Ordered[T].
       def this()=this(0)

Хотя, если я попытаюсь передать неявный параметр напрямую, вот так:

class A[T] private(a:Int)(implicit conv:T=>Ordered[T]){ 
  def this()=this(0)(conv)
}

Я получаю это:

error: not found: value conv
       def this()=this(0)(conv)

Как передать неявный параметр в этом случае?

РЕДАКТИРОВАТЬ: после некоторых экспериментов кажется, что переопределение конструктора с неявным параметром является проблемой. Не факт, что конструктор приватный.


person Krle    schedule 19.10.2016    source источник


Ответы (2)


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

class A[T] private(a:Int)(implicit conv:T=>Ordered[T]){ 
  def this()(implicit conv:T=>Ordered[T])=this(0)
}

Я прошу прощения за спам ТАК, в любом случае я приму любой ответ, который дает более подробное объяснение.

person Krle    schedule 19.10.2016
comment
Вам не нужно извиняться, ответы на ваши вопросы вполне приемлемы. - person Alexey Romanov; 19.10.2016
comment
@Krle В моей книге довольно сильный запах кода. Правильный отступ кода для одного был бы хорошим началом, но я бы не стал этого делать. Вместо этого я бы переместил этот перегруженный конструктор в сопутствующий метод apply с тем же неявным, который выглядит немного чище. - person flavian; 22.10.2016
comment
@flavian Спасибо, я так и сделаю. Но не могли бы вы уточнить, почему? Как для отступа, так и для сопутствующего объекта... - person Krle; 26.10.2016

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

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

Что бы я сделал, это:

class A[T : Ordering] private(a: Int)

На самом деле это сокращенный синтаксис для:

class A[T] private(a: Int)(implicit ev: Ordering[T])

Затем вы можете использовать этот аргумент либо явно, либо implicitly. Если вы определите его с помощью сокращенного синтаксиса T : Ordering.

class A[T : Ordering] private(a: Int) {
  def revSorter(list: List[T]): List[T] = {
    list.sorted(implicitly[Ordering[T]].reverse)
  }
}

Если вы определите его с «явным» синтаксисом:

class A[T] private(a: Int)(implicit ev: Ordering[T]) {
      def revSorter(list: List[T]): List[T] = {
        list.sorted(ev.reverse)
      }
    }
person flavian    schedule 19.10.2016
comment
Да, я согласен с ограничениями контекста, но я думаю, что основной вопрос был в том, как переопределить конструктор с неявными параметрами. В этом примере мне следовало использовать общий класс B, а не Ordered[T]. - person Krle; 20.10.2016