2016-08-18 3 views
2

que j'ai une configuration de code comme celui ci-dessousArrêt de la méthode d'appeler: après

(defgeneric move (ship destination)) 

(defmethod move (ship destination) 
    ;; do some fuel calculation here 
) 

(defmethod move :after ((ship ship) (dest station)) 
    ;; do things specific to landing on a station here 
) 

(defmethod move :after ((ship ship) (dest planet)) 
;; do things specific to landing on a planet here 
) 

Disons que maintenant, je veux déplacer mon vaisseau spatial à une station, mais les résultats de calcul de carburant à un montant négatif de carburant sur le navire (c'est-à-dire qu'il n'y en a pas assez pour le voyage).

Y a-t-il un moyen pour moi d'empêcher le qualificatif :after d'être appelé sans nécessairement signaler une condition d'erreur? Si je n'arrête pas l'appel, le navire sera déplacé vers le nouvel emplacement sans aucune soustraction de carburant, ce qui interrompt essentiellement le jeu.

+0

Vous devriez probablement déplacer le calcul de carburant vers une méthode ': AROUND' et transformer les deux méthodes': AFTER' en méthodes primaires. – jkiiski

+0

@jkiiski comment puis-je arrêter les méthodes primaires d'être appelé? –

+0

Vous ne l'appelez simplement pas. Les méthodes ': AROUND' doivent utiliser' CALL-NEXT-METHOD' manuellement pour appeler la méthode primaire, donc vous pouvez avoir quelque chose comme '(when (fuel-suffisant) (call-next-method))'. – jkiiski

Répondre

4

Vous pouvez mettre le calcul du combustible dans une méthode :AROUND et transformer les deux méthodes :AFTER en méthodes primaires. :AROUND méthodes doivent utiliser CALL-NEXT-METHOD manuellement pour appeler la méthode primaire, de sorte que vous pouvez faire quelque chose comme (when (sufficient-fuel) (call-next-method)) pour l'appeler seulement quand il y a assez de carburant.

2

Notez que conditions ne sont pas nécessairement erreurs. Une erreur est une condition spécifique, où l'exécution normale du programme ne peut pas continuer correctement sans une forme d'intervention. Le système de condition peut également être utilisé pour d'autres situations . Le Lisp commun a également catch et throw pour le transfert de contrôle non local.

Le lancer sera attrapé par un attraper, au sein de son extension dynamique, en utilisant un tag spécifique.

La méthode extérieure :around établit un capteur de sortie pour l'étiquette exit-move.

(defmethod move :around (ship destination) 
    (catch 'exit-move (call-next-method))) 

Les méthodes internes, comme les méthodes primaires peuvent transférer le contrôle à l'catch ci-dessus, en utilisant throw avec l'étiquette de prise droite exit-move. La méthode primaire sera toujours utilisée à l'intérieur la autour de la méthode, ainsi le attraper l'étiquette sera toujours jetable de lui.

(defmethod move (ship destination) 
    (print (list :primary ship destination)) 
    (when (thing-happened-p) 
    (throw 'exit-move nil)))