2017-06-18 11 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と方法を見つけるように頼まれたのですか? 3つの引数の代わりに、2を使用して、より具体的な方法、からそれを呼び出すために、私たちはあまり具体的なwithdrawメソッドの引数を持つcall-next-methodを提供できるよう

はここで、主withdraw機能は、二つの引数acctamtを持っていました。しかし、これはまだ動作していません。
何かお手伝いしました。一般的な機能のための

+5

同じ汎用関数内に2つの必須パラメータと3つの必須引数を持つメソッドを持つことはできません。 CLOSはそれを許さない。最初のメソッド定義は、必要な引数の数を決定します。サンプルの汎用関数には2つの必須の引数があり、必要な3つの引数を持つメソッドを定義しようとします。これはサポートされておらず、許可されていません。 –

+0

ありがとう@RainerJoswig。そのような方法を支持しない理由は何ですか? – Mooncrater

+0

引数を指定して 'call-next-method'を使用して次に具体的なメソッドを呼び出す点は何ですか?すべてのメソッドが同じ数の引数を必要とするため。 (したがって、同じ引数) – Mooncrater

答えて

7

合同ラムダリストの一般的な機能の

方法はcongruentラムダリストを持っている必要があります。言語標準は、それが意味することを記述する:Congruent Lambda-lists for all Methods of a Generic Function

あなたが最初のルールを見ることができるように述べている:

  • 各ラムダリストは、必要なパラメータの数が同じでなければなりません。

必須パラメータは、常にが提供されなければならないの引数を教え。汎用関数は、オプション、キーワード、および残りの引数を追加で許可します。しかし、これ以上の派遣はありません。派遣は、必要な議論とそれらすべての議論の上でのみ機能します。

必要なパラメータの数を同じにすると、ディスパッチが容易になり、コンパイラは誤った数の引数で関数呼び出しをチェックできます。

オプションのパラメータは、一般的な機能のすべてのメソッドは、オプションのパラメータの同じ番号を持つ必要があることも、合同であるには余りにも

注意が必要です。標準の第2のルールを参照してください。

言葉遣い

  • パラメータ引数は関数の呼び出し

実施例に提供されたラムダリストで指定された変数のようなもの

  • です。

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

    aおよびbは、fooのパラメータであり、である。

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

    520は機能fooの呼び出しのための2つの引数です。