2010-02-16 2 views
6

Я очень новичок в Scala.Scala: Ограничение по типу класса

Я хочу реализовать общий матричный класс класса Matrix [T] ". Единственным ограничением на T должно быть то, что T должен реализовать функцию «+» и «*» mothod /. Как мне это сделать?

Например, я хочу иметь возможность использовать как Int, Double, так и мои собственные определенные типы, например. Комплекс

Я думал что-то вдоль линий:

class Matrix[T <: MatrixElement[T]](data: Array[Array[T]]) { 
    def *(that: Matrix) = ..// code that uses "+" and "*" on the elements 
} 
abstract class MatrixElement[T] { 
    def +(that: T): T 
    def *(that: T): T 
} 
implicit object DoubleMatrixElement extends MatrixElement[Double]{ 
    def +(that: Double): Double = this + that 
    def *(that: Double): Double = this * that 
} 
implicit object ComplexMatrixElement extends MatrixElement[Complex]{ 
    def +(that: Complex): Complex = this + that 
    def *(that: Complex): Complex = this * that 
} 

всех проверки типа, но я до сих пор не могу создать экземпляр матрицы. Мне не хватает неявного конструктора? Как я могу это сделать? Или я совершенно ошибаюсь в своем методе?

Заранее спасибо Troels

ответ

4

Наконец нашел ответ :-) Я думаю, что я не был, что далеко в моей первой попытки , Вот он идет: (написано на Скале 2.8)

trait MatrixElement[T] { 
    def +(that: T): T 
    def *(that: T): T 
} 

object MatrixElement { 
    implicit def intToMatrixElement(x : Int) = new MatrixElement[Int] { 
     def +(y : Int) = x + y 
     def *(y : Int) = x * y 
    } 
    implicit def doubleToMatrixElement(x : Double) = new MatrixElement[Double] { 
     def +(y : Double) = x + y 
     def *(y : Double) = x * y 
    } 
    implicit def complexToMatrixElement(x : Complex) = new MatrixElement[Complex] { 
     def +(y : Complex) = x + y 
     def *(y : Complex) = x * y 
    } 
} 

class Matrix[T <% MatrixElement[T] : ClassManifest ](d: Array[Array[T]]) { 
    def *(that: Matrix) = ..// code that uses "+" and "*" on the elements 
} 

Теперь я могу делать такие вещи, как:

scala> new Matrix(Array(Array(1,0),Array(0,1))) 
res0: Matrix[Int] = 
1 0 
0 1 

scala> new Matrix(Array(Array(new Complex(0),new Complex(1)),Array(new Complex(1),new Complex(0)))) 
res9: Matrix[Complex] = 
(0.0,0.0i) (1.0,0.0i) 
(1.0,0.0i) (0.0,0.0i) 
4

Вы можете использовать Numeric для Scala 2.8 для этого. Описывается here. Он заменит MatrixElement и его реализации:

class Matrix[T : Numeric](data: Array[Array[T]]) { 
    def *(that: Matrix[T]) = // 
} 
+0

Я считал Numeric. Но я действительно не вижу, как это будет работать для моих собственных типов, например. Сложный. Я бы подумал, что Complex тогда потребуется расширить Numeric. Что в первую очередь потребует от меня реализовать гораздо больше методов, чем просто + и *. Среди этих заказов - насколько я знаю, нет строгих заказов на комплексные числа. Ключевым моментом является то, что мне нужна матрица для работы над любыми типами, которые просто заполняют эти методы + и *. –

+0

Существует множество методов для реализации, если вам нужны только + и *. Но вы все равно можете создать что-то вроде Numeric только с этими двумя методами. Это должно быть две работы. (И, возможно, вернитесь позже и замените его на числовое, если это стоит.) –

+1

@troels Вы всегда можете заказать реальную часть или просто вернуть «0» для всех сравнений. И вы всегда можете «реализовать» методы с помощью 'error (« Undefined method »)'. Обратите внимание, однако, что 'Complex' не будет _extend_' Numeric'. Вместо этого будет экземпляр «Numeric [Complex]». –

2

Вот как Numeric решение будет выглядеть:

// ': Numeric[T]' adds an implicit parameter to the constructor, 
// which allows T to be used in arithmetic expressions. 
class Matrix[T: Numeric](val data: Array[Array[T]]) { 
    def *(that: Matrix[T]) = { 
     val nt = implicitly[Numeric[T]] 
     import nt._ // This imports an Implicit View to allow operator syntax 

     this.data(0)(0) * that.data(0)(0) 
     // etc 
    } 
} 
+0

'T: Числовой [T]' должен быть 'T: Numeric'. Вы пишете это без REPL? :-) –

+0

Упс! Поймал меня :) – retronym

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

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