Scala: можно ли указать универсальный класс, который реализует определенный метод - PullRequest
10 голосов
/ 15 января 2012

Я думаю, что это проще объяснить на простом примере. (помощь в перефразировании названия приветствуется; -)

Я бы хотел реализовать метод squared и, используя implicit def, автоматически добавить его в любой класс, поддерживающий оператор *.

С Int это очень просто:

class EnhancedInt(x: Int) { def squared = x * x }

implicit def IntToEnchancedInt(x: Int) = new EnhancedInt(x)

Но с Any или AnyVal я получаю следующую ошибку:

scala> class EnhanceAny(x: AnyVal) { def squared = x * x }
<console>:7: error: value * is not a member of AnyVal
       class EnhanceAny(x: AnyVal) { def squared = x * x }

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

Ответы [ 3 ]

8 голосов
/ 15 января 2012

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

Вы можете довольно близко приблизиться к тому, что вы хотите, используя класс типов вместе с классом Numeric (вдохновленный ответами на это и это вопрос).Это будет работать с большинством примитивов:

//define the type class
trait Multipliable[X] { def *(x: X): X}

//define an implicit from A <% Numeric[A] -> Multipliable[Numeric[A]]
implicit def Numeric2Mult[A](a: A)(implicit num: Numeric[A]): Multipliable[A] = new Multipliable[A]{def *(b: A) = num.times(a, b)}

//now define your Enhanced class using the type class
class EnhancedMultipliable[T <% Multipliable[T]](x: T){ def squared = x * x}

//lastly define the conversion to the enhanced class
implicit def Mult2EnhancedMult[T <% Multipliable[T]](x: T) = new EnhancedMultipliable[T](x)

3.squared
//Int = 9

3.1415F.squared
//Float = 9.869022

123456789L.squared
//Long = 15241578750190521
0 голосов
/ 15 января 2012

Подумай об этом.Умножение имеет разные свойства на разных объектах .Например, целочисленное умножение ассоциативно и коммутативно, скалярное умножение не коммутативно.И умножение на числа с плавающей запятой ... Но, конечно, вы можете иметь то, что вы хотите, с чертой или с "чертой и неявной" конструкцией, которая напоминает класс типов.

0 голосов
/ 15 января 2012
...