LISP-CLOS


Common LISP 的出现比面向对象编程的发展早了几十年。然而,面向对象是在后来才被纳入其中的。

定义类

defclass宏允许创建用户定义的类它建立一个类作为数据类型。它具有以下语法 -

(defclass class-name (superclass-name*)
   (slot-description*)
   class-option*))

槽是存储数据或字段的变量。

插槽描述的形式为 (slot-name slot-option*),其中每个选项都是一个关键字,后跟名称、表达式和其他选项。最常用的插槽选项是 -

  • :访问器函数名称

  • :initform表达式

  • :initarg符号

例如,让我们定义一个 Box 类,具有三个插槽长度、宽度和高度。

(defclass Box () 
   (length 
   breadth 
   height)
)

提供对插槽的访问和读/写控制

除非槽具有可以访问、读取或写入的值,否则类是毫无用处的。

您可以在定义类时为每个槽指定访问器。例如,以我们的 Box 类为例 -

(defclass Box ()
   ((length :accessor length)
      (breadth :accessor breadth)
      (height :accessor height)
   )
)

您还可以为读取和写入插槽指定单独的访问器名称。

(defclass Box ()
   ((length :reader get-length :writer set-length)
      (breadth :reader get-breadth :writer set-breadth)
      (height :reader get-height :writer set-height)
   )
)

创建类的实例

通用函数make-instance创建并返回类的新实例。

它具有以下语法 -

(make-instance class {initarg value}*)

例子

让我们创建一个 Box 类,具有三个槽,长度、宽度和高度。我们将使用三个槽访问器来设置这些字段中的值。

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
   )
)
(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(format t "Length of the Box is ~d~%" (box-length item))
(format t "Breadth of the Box is ~d~%" (box-breadth item))
(format t "Height of the Box is ~d~%" (box-height item))

当您执行代码时,它会返回以下结果 -

Length of the Box is 10
Breadth of the Box is 10
Height of the Box is 5

定义类方法

defmethod宏允许您类内定义方法。下面的示例扩展了我们的 Box 类以包含名为volume的方法。

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   

(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)

 ;setting the values 

(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)

; displaying values

(format t "Length of the Box is ~d~%" (box-length item))
(format t "Breadth of the Box is ~d~%" (box-breadth item))
(format t "Height of the Box is ~d~%" (box-height item))
(format t "Volume of the Box is ~d~%" (volume item))

当您执行代码时,它会返回以下结果 -

Length of the Box is 10
Breadth of the Box is 10
Height of the Box is 5
Volume of the Box is 500

遗产

LISP 允许您根据另一个对象来定义一个对象。这称为继承。您可以通过添加新的或不同的功能来创建派生类。派生类继承了父类的功能。

下面的例子解释了这一点 -

例子

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   
(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)
  
;wooden-box class inherits the box class  
(defclass wooden-box (box)
((price :accessor box-price)))

;setting the values 
(setf item (make-instance 'wooden-box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(setf (box-price item) 1000)

; displaying values
(format t "Length of the Wooden Box is ~d~%" (box-length item))
(format t "Breadth of the Wooden Box is ~d~%" (box-breadth item))
(format t "Height of the Wooden Box is ~d~%" (box-height item))
(format t "Volume of the Wooden Box is ~d~%" (volume item))
(format t "Price of the Wooden Box is ~d~%" (box-price item))

当您执行代码时,它会返回以下结果 -

Length of the Wooden Box is 10
Breadth of the Wooden Box is 10
Height of the Wooden Box is 5
Volume of the Wooden Box is 500
Price of the Wooden Box is 1000