2017-06-18 51 views
0

考慮類account呼叫下一個最具體的方法是行不通的

(defclass account() 
    ((name :initarg :name :reader name) 
    (balance :initarg :balance :initform 0.00 :accessor balance) 
    (interest-rate :allocation :class :initform 0.06 
        :reader interest-rate))) 

對於這個類,我們定義了一個方法withdraw

(defmethod withdraw ((acct account) amt) 
    (if (< amt (balance acct)) 
     (decf (balance acct) amt) 
     'insufficient-funds)) 

而且,另一個類password-account,即account的子類:

(defclass password-account (account) 
    ((password :initarg :password :reader password))) 

而且,該方法withdraw,該類:

(defmethod withdraw ((acct password-account) amt pass) 
    (if (equal (password acct) pass) 
     (call-next-method acct amt) 
     'wrong-password)) 

但是,這給出了一個錯誤:

The generic function 
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::WITHDRAW (1)> 
takes 2 required arguments; was asked to find a method with 
specializers 
(#<STANDARD-CLASS COMMON-LISP-USER::PASSWORD-ACCOUNT> 
#1=#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T> #1#) 
    [Condition of type SB-PCL::FIND-METHOD-LENGTH-MISMATCH] 
See also: 
    Common Lisp Hyperspec, FIND-METHOD [:function] 

Restarts: 
0: [RETRY] Retry SLIME REPL evaluation request. 
1: [*ABORT] Return to SLIME's top level. 
2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1005308033}>) 

這究竟是爲什麼?又是什麼

被要求找到specializers的方法

這裏的意思?

這裏,主withdraw函數有兩個參數acctamt,所以爲了從一個更具體的方法,它使用的2 3個參數,而不是調用它,我們可以提供call-next-method與較不具體withdraw方法的參數。但是這仍然不起作用。
任何幫助表示讚賞。

+5

在同一個泛型函數中,不能有兩個必需參數和另一個需要三個參數的方法。 CLOS不允許這樣做。第一個方法定義確定所需參數的數量。在你的例子中的泛型函數有兩個必需的參數,你試圖用三個必需的參數來定義一個方法。這不被支持,也不被允許。 –

+0

謝謝@RainerJoswig。不支持這些方法的任何特定原因? – Mooncrater

+0

通過帶參數的'call-next-method'調用下一個最具體的方法有什麼意義?因爲所有的方法都需要相同數量的參數。 (因此相同的參數) – Mooncrater

回答

7

全等拉姆達列出了通用功能通用功能的

方法需要有congruent拉姆達名單。語言標準描述了這個意思:Congruent Lambda-lists for all Methods of a Generic Function

正如你所看到的第一條規則說:

  • 每個拉姆達列表必須具有相同數量的必要的參數。

必需的參數告訴我們要提供的參數總是有。通用函數還允許可選的關鍵字和休息參數。但沒有派遣這些。派遣只適用於所需的參數和所有這些。

具有相同數量的所需參數使調度更容易,並允許編譯器檢查具有錯誤數量參數的函數調用。

可選參數必須是一致的,也

還要注意的是一個通用的函數的所有方法都需要有相同數量的可選參數。請參閱標準中的第二條規則。

措辭

  • 一個參數是像
  • 參數是在呼叫提供給函數

例子在拉姆達列表中指定的變量:

(defun foo (a b) (list a b)) 

ab參數功能foo

(foo (+ 2 3) (* 4 5)) 

520是兩個參數的功能foo的召喚。