(defclass shape () ()
(:documentation "The foundation of all shapes."))
(defclass triangle (shape)
((a :reader side-a :initarg :side-a)
(b :reader side-b :initarg :side-b)
(c :reader side-c :initarg :side-c)))
;; Constructor
(defun make-triangle (a b c)
;; All sides should be represented as floats
(make-instance 'triangle :side-a (coerce a 'float)
:side-b (coerce b 'float)
:side-c (coerce c 'float)))
;; The function three-sides-to-angle will be useful in the bodies of the
;; methods that return the angles of the triangle.
;;; Return the angle A between adjacent sides b and c
;;; and opposite side a, given all sides of a triangle
;;; Law of Cosine: a^2 = b^2 + c^2 - 2 bc(cos A)
(defun three-sides-to-angle (a b c)
(acos (/ (- (+ (expt b 2)
(expt c 2))
(expt a 2))
(* 2 b c))))
;; Next, we define the methods for returning the individual angles of a
;; triangle.
(defmethod angle-A ((tri triangle))
(three-sides-to-angle
(side-a tri) (side-b tri) (side-c tri)))
(defmethod angle-B ((tri triangle))
(three-sides-to-angle
(side-b tri) (side-c tri) (side-a tri)))
(defmethod angle-C ((tri triangle))
(three-sides-to-angle
(side-c tri) (side-a tri) (side-b tri)))
;; We choose to define explicitly the generic functions for the operations
;; that are part of the exturnal protocol. The defgeneric forms indicate
;; that these three operations are intended to work on any shape:
(defgeneric dimensions (shape)
(:documentation "Returns list of side lengths."))
(defgeneric angles (shape)
(:documentation "Returns list of angles."))
(defgeneric area (shape)
(:documentation "Returns area of the shape."))
;; The three external operations that deal with existing triangles can be
;; defined in terms of the internal operations, without depending on any
;; knowledge of how those internal operations are implemented.
(defmethod dimensions ((tri triangle))
(list (side-a tri)
(side-b tri)
(side-c tri)))
(defmethod angles ((tri triangle))
(list (side-A tri)
(side-B tri)
(side-C tri)))
;;; Return the area of a triangle
;;; Algorithm is: area = ab(sin C) / 2
(defmethod area ((tri triangle))
(* (side-a tri) (side-b tri)
(sin (angle-C tri))
.5))
Как получить результаты от defmethod, defgeneric
CL-USER> (make-triangle 20 30 40)
#<TRIANGLE {100300A2B3}>
CL-USER> (three-sides-to-angle 20 30 40)
0.5053605
CL-USER> (three-sides-to-angle 60 40 80)
0.8127556
Попробовал, а он мне вот
CL-USER> (dimensions triangle)
; Evaluation aborted on #<UNBOUND-VARIABLE TRIANGLE {10030E3E33}>.
CL-USER> (dimensions 'triangle)
; Evaluation aborted on #<SB-PCL::NO-APPLICABLE-METHOD-ERROR {100344E173}>.
CL-USER> (angle-A tri)
; Evaluation aborted on #<UNBOUND-VARIABLE TRI {10035E79E3}>.
Source: Sonya Keene Object-oriented programming in Common Lisp.