2008-11-18 27 views

Trả lời

17

Có và không. Có, bạn có thể làm cho nó dường như giống như bạn đã thêm phương thức vào double. Ví dụ:

class MyRichDouble(d: Double) { 
    def <>(other: Double) = d != other 
} 

implicit def doubleToSyntax(d: Double) = new MyRichDouble(d) 

Mã này thêm <> điều hành trước đó không có sẵn cho bất kỳ đối tượng kiểu Double. Vì vậy, miễn là phương pháp doubleToSyntax là trong phạm vi sao cho nó có thể được gọi mà không cần trình độ chuyên môn, sau đây sẽ làm việc:

3.1415 <> 2.68  // => true 

Các "không" một phần của câu trả lời xuất phát từ thực tế là bạn không thực sự thêm bất cứ điều gì đến lớp học Double. Thay vào đó, bạn đang tạo chuyển đổi từ Double thành loại mới xác định phương thức bạn muốn. Đây có thể là một kỹ thuật mạnh hơn nhiều so với các lớp mở được cung cấp bởi nhiều ngôn ngữ động. Nó cũng xảy ra hoàn toàn an toàn kiểu. :-)

Một số hạn chế bạn nên biết:

  • Kỹ thuật này không cho phép bạn để loại bỏ hoặc xác định lại phương pháp hiện có, chỉ cần thêm những cái mới
  • Phương pháp chuyển đổi ngầm (trong trường hợp này, doubleToSyntax) hoàn toàn phải nằm trong phạm vi cho phương pháp tiện ích mong muốn có sẵn

Tự nhiên, ngầm định c các đảo ngược được đặt trong các đối tượng đơn lẻ và được nhập (ví dụ: import Predef._) hoặc trong các đặc điểm và được kế thừa (ví dụ: class MyStuff extends PredefTrait).

Nhẹ sang một bên: "toán tử kết nối" trong Scala thực ra là phương pháp. Không có phép thuật nào liên quan đến phương thức <> cho phép nó được nhúng, trình phân tích cú pháp đơn giản chấp nhận nó theo cách đó. Bạn cũng có thể sử dụng "phương thức thông thường" làm toán tử nếu bạn muốn. Ví dụ: lớp Stream xác định phương thức take lấy một tham số Int duy nhất và trả lại Stream mới. Điều này có thể được sử dụng theo cách sau:

val str: Stream[Int] = ... 
val subStream = str take 5 

Khái niệm str take 5 là nghĩa đen giống hệt nhau để str.take(5).

+0

Bạn có thể sử dụng cú pháp 'ngầm class' để đơn giản hóa này một chút. – lmm

1

Tính năng này đã có ích để thực hiện một ước lượng lỗi lớp biểu diễn:

object errorEstimation { 
    class Estimate(val x: Double, val e: Double) { 
    def + (that: Estimate) = 
     new Estimate(this.x + that.x, this.e + that.e) 
    def - (that: Estimate) = 
     new Estimate(this.x - that.x, this.e + that.e) 
    def * (that: Estimate) = 
     new Estimate(this.x * that.x, 
        this.x.abs*that.e+that.x.abs*this.e+this.e*that.e) 
    def/(that: Estimate) = 
     new Estimate(this.x/that.x, 
        (this.x.abs*that.e+that.x.abs*this.e)/(that.x.abs*(that.x.abs-that.e))) 
    def +- (e2: Double) = 
     new Estimate(x,e+e2) 
    override def toString = 
     x + " +- " + e 
    } 
    implicit def double2estimate(x: Double): Estimate = new Estimate(x,0) 
    implicit def int2estimate(x: Int): Estimate = new Estimate(x,0) 

    def main(args: Array[String]) = { 
    println(((x: Estimate) => x+2*x+3*x*x)(1 +- 0.1)) 
    // 6.0 +- 0.93 
    println(((x: Estimate) => (((y: Estimate) => y*y + 2)(x+x)))(1 +- 0.1)) 
    // 6.0 +- 0.84 
    def poly(x: Estimate) = x+2*x+3/(x*x) 
    println(poly(3.0 +- 0.1)) 
    // 9.33333 +- 0.3242352 
    println(poly(30271.3 +- 0.0001)) 
    // 90813.9 +- 0.0003 
    println(((x: Estimate) => poly(x*x))(3 +- 1.0)) 
    // 27.037 +- 20.931 
    } 
} 
+0

Đó là thực sự kinda gọn gàng. :) –

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