2011-09-06 27 views
11

Nói rằng tôi đang xác định một lớp điểm 2D đơn giản trong Scala, và tôi muốn để có thể xây dựng nó với các loại khác nhau:Tại sao các tham số kiểu được cho phép trong các nhà xây dựng phụ trợ của Scala?

class Point(x:Float, y:Float) { 
    this(x:Double, y:Double) = this(x.toFloat, y.toFloat) 
    this(x:Int, y:Int) = this(x.toFloat, y.toFloat) 
    // etc... 
} 

Tôi muốn đun sôi này xuống bằng một mẫu, chẳng hạn như:

class Point(x:Float, y:Float) { 
    this[T](x:T, y:T) = this(x.toFloat, y.toFloat) 
} 

tôi biết điều này sẽ không làm việc dù sao, kể từ khi T có thể là một loại mà toFloat không được định nghĩa, nhưng lỗi biên dịch tôi nhận được là:

no type parameters allowed here

đây có phải là chỉ unsupp in ở Scala? Nếu vậy, tại sao, và có cách nào đơn giản để giải quyết vấn đề này không?

Trả lời

14

Các hàm tạo lớp của Scala (không giống Java) không thể lấy tham số kiểu, chỉ có chính lớp đó mới có thể. Về lý do tại sao Scala thực hiện lựa chọn thiết kế này, tôi cho rằng lý do chính là đơn giản.

Nếu bạn muốn có phương thức "người xây dựng" phụ chung, điều tự nhiên cần làm là xác định nó trên đối tượng đồng hành. Ví dụ,

object Point { 
    def build[T : Numeric](x: T, y: T) = { 
    val n = implicitly[Numeric[T]] 
    new Point(n.toFloat(x), n.toFloat(y)) 
    } 
} 

class Point(val x:Float, val y:Float) 

val p = Point.build(1, 2) // Companion object's builder 
p.x + p.y 

Ở đây tôi đã sử dụng Numeric typeclass để có được một toFloat generic method.

+1

Nếu bạn gọi phương thức này là 'áp dụng' thì bạn có thể viết,' val p = Điểm (1,2) ', không? –

+1

Có, và đó là cách các trường hợp thực hiện. –

3

tôi đã chơi với điều này cho một lúc, nhận được là "gần" như ...

class Point(x:Float, y:Float) { 
    def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat) 
} 

... mà kết quả trong "lỗi: không có thông số loại được phép ở đây" (chỉ cần theo bưu điện) và sau đó tôi nhận ra ...

Nếu trình khởi tạo có thể lấy tham số kiểu, nó sẽ không rõ ràng với tham số lớp, nếu có. Không phải là điều này không thể được làm việc về trong các đặc điểm kỹ thuật ngôn ngữ ... nhưng nó là một trường hợp phức tạp hơn ít nhất. Cũng có thể có các vấn đề tương thích với Java.

Hãy tưởng tượng:

class Foo[T](x: T) { 
    def this[X](z: X) = ... 
} 
new Foo[Int](42) // T is Int? X is ...? Or ...? 

Cá nhân tôi muốn Scala theo một mô hình Eiffel-tương tự (chỉ có tên nhà thầu hoặc "phương pháp nhà máy"), nhưng than ôi, điều đó sẽ không được Scala.

Mã hóa vui vẻ.

Các vấn đề liên quan