2011-11-06 25 views

Trả lời

11

Bạn không thể vá khỉ, thay đổi các đối tượng đã tồn tại. Tuy nhiên, bạn có thể viết một chuyển đổi ẩn ẩn hoạt động theo cùng một cách (và được cho là an toàn hơn) trong hầu hết các trường hợp.

Trước hết, với unless như được viết, bạn không cần nó là phương thức của mọi lớp. Chỉ cần dính nó vào một số đối tượng và nhập khẩu.

object Utility { 
    def unless(condition: => Boolean)(body: => Unit):Unit = if(!condition) body 
} 

import Utility._ 

Nhưng đôi khi bạn làm muốn nó đóng vai trò như một phương pháp trên một lớp. Ví dụ, tôi thường viết

option.map(x => f(x)).getOrElse(default) 

có thể được gọn hơn bằng văn bản như một lần:

option.fold(default)(x => f(x)) 

trừ Option mà không có nếp gấp. Vì vậy, tôi:

class OptionWrapper[A](o: Option[A]) { 
    def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default) 
} 
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o) 

(đây được gọi là mẫu "pimp my library"). Bây giờ tôi có thể sử dụng nội dung trái tim của tôi, vì bất cứ lúc nào có một tùy chọn và tôi gọi phương thức fold, trình biên dịch nhận ra rằng không có phương pháp fold và tìm kiếm bất kỳ cách nào để chuyển đổi lớp thành thứ gì đó fold. Có một phương thức như vậy và lớp mới thực hiện tùy chọn hiện tại chính xác những gì bạn muốn từ phương thức fold trên chính lớp đó.

+0

Về "được cho là an toàn hơn", hãy tranh luận. Làm thế nào là một chuyển đổi tiềm ẩn an toàn hơn khỉ vá? Nó vẫn cho phép các đối tượng sử dụng các phương thức mà lớp gốc không có sẵn. –

+0

@ DanBurton tại sao bạn không hỏi nó như một câu hỏi? –

+5

@Dan Burton - Với bản vá khỉ, bạn có thể có một kết hợp các đối tượng mà một số trong đó có một phương pháp và một số trong đó không có; điều này làm tăng các vấn đề mà bạn mong đợi một đối tượng có một phương thức nhưng nó chưa được vá (hoặc phiên bản sai đã được vá). Với chuyển đổi tiềm ẩn, bạn có tính an toàn kiểu thời gian biên dịch: các lớp được đảm bảo có các phương thức mà chúng có và các chuyển đổi được đảm bảo hoạt động. –

2

Nếu tất cả các lớp học của bạn đang được một gói duy nhất (và nhớ gói can be nested trong Scala!), Bạn có thể đặt định nghĩa của bạn trong một package object.

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