2012-10-13 31 views
14

Tôi muốn biết tại sao defmulti & defmethod được sử dụng? Ưu điểm là gì? Và bạn sử dụng nó như thế nào? Vui lòng giải thích những gì đang xảy ra trong mã.làm thế nào và tại sao defmulti và defmethod được sử dụng? và những lợi thế là gì?

+0

Are bạn có thể định nghĩa multimethod là gì? Nếu không thì tôi sẽ vui lòng giải thích cho bạn – tgoossens

+0

Đây là câu hỏi mà tôi từng hỏi: http://cs.stackexchange.com/questions/4660/difference-between-multimethods-and-overloading Tôi đã trả lời câu hỏi của riêng mình Đồng thời, điều này có thể giúp bạn hiểu được đa phương thức là gì – tgoossens

Trả lời

25

Trong "một cách chung chung" bạn sẽ gọi nó là một if/else trên steroid và trong "gây ấn tượng với tôi" phong cách bạn sẽ đặt tên cho nó với "cử động", "thời gian chạy đa hình" vv

Cho phép nói rằng bạn muốn để xác định một chức năng "Add" mà nên làm việc cho các loại dữ liệu khác nhau như trong trường hợp Int nó nên thêm các con số, trong trường hợp của chuỗi nó nên concat các chuỗi. Bây giờ nó là rất đơn giản để thực hiện nó bằng cách sử dụng nếu khác, về cơ bản bạn kiểm tra các loại đối số và nếu họ là số nguyên sau đó thêm chúng, nếu họ là chuỗi sau đó concat họ khác ném ngoại lệ. Nhưng vấn đề với điều này là trong trường hợp bạn muốn thêm hỗ trợ cho kiểu dữ liệu mới trong hàm Add của bạn, bạn cần phải sửa đổi chức năng Thêm, có thể không thực hiện được trong trường hợp bạn không kiểm soát nguồn Thêm chẳng hạn như trường hợp nó được định nghĩa trong một số thư viện, vv defmultidefmethod cho phép bạn giải quyết vấn đề này tức là thêm trường hợp mới vào hàm hiện có mà không sửa đổi mã của nó.

(defmulti add (fn [a b] [(type a) (type b)]))

add là tên hàm, hàm nặc danh là bạn if/else, về cơ bản này sẽ được gọi trên đối số add bạn và giá trị trả về của hàm này sẽ được kiểm tra nếu có bất kỳ thực hiện. Bây giờ hãy thực hiện nó cho Integer.

(defmethod add [Integer Integer] ([a b] (+ a b)))

[Integer Integer] được loại chuyển trường hợp trên giá trị trả về của hàm nặc danh chúng tôi quy định tại defmulti và sau đó thực hiện.

Tương tự như vậy chúng ta có thể làm cho các chuỗi

(defmethod add [String String] ([a b] (str a b)))

Gọi nó với số nguyên (add (int 1) (int 2))

Gọi nó với chuỗi (add "hello" "world")

Gọi nó với cái gì đó không phù hợp với chúng tôi nếu/else tức là không thực hiện được cho một trường hợp sẽ dẫn đến một ngoại lệ

+2

Cảm ơn bạn rất nhiều! Điều này là rất hữu ích! – Phil

+0

Cảm ơn bạn đã giải thích! – goncalvesnelson

7

Từ những gì tôi đã quan sát thấy sau khi đọc câu trả lời (và sử dụng các ví dụ được cung cấp ở trên), sau đây cũng là hữu ích để hiểu:

khi bạn thực hiện lệnh:

(add (int 5) (int 2)) 

gì xảy ra là rằng 'thêm defmulti' như vậy được thực hiện sản xuất một danh sách:

[Integer Integer] 

với điều đó được sản xuất, có vẻ đối với bất kỳ 'thêm defmethod' được xác định với danh sách ví dụ trên:

(add [Integer Integer]) 

Và chuyển các đối số mà nó nhận được.

Một cách khác để xác định các phương pháp đa để làm việc thông qua các đối số rõ ràng là:

(defmulti add (fn [a b] [(type a) (type b)])) 
(defmethod add [Integer Integer] [a b] (+ a b)) 
(defmethod add [String String] [a b] (str a b)) 

Sau đó chạy các chức năng như:

(add 12 73) 

hoặc

(add "thank" "you") 
Các vấn đề liên quan