(Translated by https://www.hiragana.jp/)
Common Lisp Object System - Wikipedia コンテンツにスキップ

Common Lisp Object System

出典しゅってん: フリー百科ひゃっか事典じてん『ウィキペディア(Wikipedia)』
CLOSから転送てんそう

Common Lisp Object System(コモン リスプ オブジェクトシステム、略称りゃくしょう CLOS)は、ANSI Common Lisp (CL) の一部いちぶをなすオブジェクト指向しこうプログラミング機能きのうであり、言語げんごEuLispEmacs LispSchemeDylan)にも類似るいじのシステムが導入どうにゅうされている[1]。1984ねんのCommon Lisp仕様しようではオブジェクト指向しこうシステムは時期じき尚早しょうそうとしてまれなかったが、1994ねんのANSI標準ひょうじゅんでは機能きのうとなった。CLOS はつよ型付かたつをもつ動的どうてき(実行じっこう定義ていぎ変更へんこうできる)オブジェクトシステムであり、C++Javaのような静的せいてきなオブジェクト指向しこう言語げんごとはおおきくことなる。1970年代ねんだいはじまる初期しょきのLISPオブジェクトシステム(MIT FlavorsLOOPS)に影響えいきょうされているが、より汎用はんようてきである。

LISPにオブジェクト指向しこう導入どうにゅうすることは簡単かんたんである。2ページ程度ていどのコードがあれば実現じつげんできる(Graham, 1994)。一方いっぽう、オブジェクト指向しこうLISPを柔軟じゅうなん拡張かくちょうせいんだものに設計せっけいするのはより困難こんなんであった。CLOS は完全かんぜんなオブジェクトシステムであり、オブジェクト指向しこうシステム自体じたいがオブジェクト指向しこうプログラミングによって拡張かくちょう可能かのうである。拡張かくちょうのプロトコルは CLOS Metaobject Protocol (MOP) とばれる。[2]

Standard Method Combination の概念がいねん

特徴とくちょう

[編集へんしゅう]

多重たじゅうディスパッチ

[編集へんしゅう]

CLOS は多重たじゅうディスパッチシステムである。すなわち、引数ひきすうデータがたによってメソッド用意よういできる。おおくのオブジェクト指向しこう言語げんご単一たんいつディスパッチであり、メソッドはだいいち引数ひきすうのデータがたでしかディスパッチできない。CLOS のメソッドは総称そうしょう関数かんすうにグループされる。総称そうしょう関数かんすうおな名前なまえ引数ひきすう構造こうぞうつ(ただし個々ここ引数ひきすうのデータがたことなる)メソッドをあつめたものである。れいによりこのことをより説明せつめいする。

よわいカプセル

[編集へんしゅう]

おおくの動的どうてきオブジェクト指向しこう言語げんごPythonなど)と同様どうよう、CLOS ではカプセルおこなわれない。任意にんいのデータ(スロット)にslot-value 関数かんすうでアクセス可能かのうである。

データ構造こうぞう関数かんすう管理かんりにあたって、CL のプログラマはパッケージというモジュール管理かんり機能きのうもちいることがおおい。

多重たじゅう継承けいしょう

[編集へんしゅう]

CLOS は多重たじゅう継承けいしょう機能きのうをもち、プログラミングスタイルとしてもMixinとして活用かつようされてもいる。標準ひょうじゅんではクラス優先ゆうせん順位じゅんいリストをトポロジカルソートする戦略せんりゃくくわえ、メソッドの起動きどう順序じゅんじょのカスタマイズとう可能かのうであり、C++とうにみられる菱形ひしがた継承けいしょう問題もんだいとう顕在けんざいしない。また、クラス優先ゆうせん順位じゅんいリストのソートの戦略せんりゃくもCLOS MOPによりクラスごとにユーザーがカスタマイズが可能かのうである。

動的どうてきクラス変更へんこう

[編集へんしゅう]

CLOSでのオブジェクトのクラスは動的どうてきであり、オブジェクトの内容ないようだけでなく「構造こうぞう」を実行じっこう変更へんこうできる。インスタンスがぞくするクラスを変更へんこうする関数かんすう(change-class INSTANCE NEW-CLASS-NAME &rest INITARGS) である。

また、CLOS は実行じっこうに(すでにそのクラスがインスタンスをっていても)クラス定義ていぎ変更へんこうできる。具体ぐたいてきには、defclass再度さいど評価ひょうかしてクラス定義ていぎ変更へんこうしたさい、CLOSは(make-instances-obsolete CLASS)す。make-instances-obsolete指定していされたクラスのすべてのインスタンスにたいしてupdate-instance-for-redefined-classす。update-instance-for-redefined-classあらたに追加ついかされたスロットや削除さくじょされたスロットの情報じょうほう引数ひきすうとしてけとり、おなじく引数ひきすうとしてったインスタンスからあたらしい定義ていぎもとづいてあらたにつくったインスタンスへをコピーする。これらみっつのメソッドは継承けいしょうによりユーザーがえ・追加ついかおこなうことができる。

クラスベース

[編集へんしゅう]

CLOS はプロトタイプベースではない。インスタンスをあるクラスのメンバーとして作成さくせいするには事前じぜんdefclassによってそのクラスを定義ていぎしなければならない。

MOP : Meta Object Protocol

[編集へんしゅう]

ANSI 標準ひょうじゅん範囲はんいがいだが、CLOS の実装じっそうひろ採用さいようされている拡張かくちょうとしてメタオブジェクトプロトコル(The Common Lisp Object System MetaObject Protocol)がある。MOP は CLOS 実装じっそう基盤きばん標準ひょうじゅんインタフェースを定義ていぎし、クラスをメタクラスのインスタンスとしてあつかい、あらたなメタクラスを定義ていぎしたり、基底きていクラスのいを修正しゅうせいしたりできる。CLOS MOP はアスペクト指向しこうプログラミング先取さきどりともえ、実際じっさいおな技術ぎじゅつしゃ(Gregor Kiczales など)がかかわっている。代表だいひょうてき機能きのうGeneric Function (class-slots class)Class standard-slot-definition、など。

MOPは実装じっそうけいによってあつかいがことなるが、その重要じゅうようせいのため、搬性を担保たんぽするこころみがおこなわれている。結果けっか現在げんざいでは、インターフェースを共通きょうつうにするライブラリ Closer to MOP がデファクトスタンダードとなっている[3]

実行じっこうメソッドの形成けいせい

[編集へんしゅう]

総称そうしょう関数かんすうしたとき実行じっこうする手続てつづきの内容ないようは、おおくの動的どうてきオブジェクト指向しこうプログラミングシステムと同様どうよう、その実行じっこう動的どうてき決定けっていされるが、メソッドキャッシュやコンパイル決定けっていできる最適さいてきもちいて高速こうそくはかっている処理しょりけいおおい。

適用てきよう可能かのうメソッドをならべる

[編集へんしゅう]

引数ひきすうかた継承けいしょう関係かんけいおうじて、適用てきようしてよいメソッドをあつめる。

クラスpersonがクラスanimal継承けいしょうしているとする。p1とp2はともpersonのインスタンスである。総称そうしょう関数かんすうreaction以下いかのような

(reaction p1 p2)

について、メソッドが以下いかのように定義ていぎされている場合ばあい

(defmethod reaction ((a1 animal) (a2 animal)) (foo)) ; 1
(defmethod reaction ((a1 person) (a2 animal)) (bar)) ; 2
(defmethod reaction ((a1 animal) (a2 person)) (baz)) ; 3
(defmethod reaction ((a1 person) (a2 person)) (bab)) ; 4

うえの4つはすべて適用てきよう可能かのうメソッドである。

クラス継承けいしょうじゅんによるメソッドのなら

[編集へんしゅう]

これら4つのメソッドは、引数ひきすうオブジェクトの継承けいしょう順序じゅんじょ(Precedence Order)したがってソートされる。 うえれいでは、さいのp1とp2がともにクラスpersonのインスタンスであるため、それにもっともマッチしている4番目ばんめのメソッドがもっとたか継承けいしょう順序じゅんじょつ。 継承けいしょう順序じゅんじょ通常つうじょう左側ひだりがわ引数ひきすうからじゅん計算けいさんされる。したがってうえれいでは、2番目ばんめと3番目ばんめのメソッドをくらべた場合ばあいだいいち引数ひきすう適用てきよう優先ゆうせんされることから、2番目ばんめ適用てきようのほうがたかくなる。[4][5] 結果けっかてきに、メソッドらは4,2,3,1のじゅんでソートされる。

メソッド結合けつごう(メソッド・コンビネーション)

[編集へんしゅう]

CLOSでは、うえのソートによってつくられたメソッドのリストに一定いってい戦略せんりゃく適用てきようすることで、最終さいしゅうてき実際じっさいおこな動作どうさ決定けっていする。この戦略せんりゃくのことをメソッド結合けつごうぶ。いくつかのバリエーションが標準ひょうじゅん定義ていぎされている。

言語げんごにおいて、あるインスタンスのメソッドをすときの動作どうさについてかんがえてみよう。そのインスタンスのクラスがしんクラスをつとき、たとえばJavaのような言語げんごにおいては、継承けいしょうされたメソッドは上書うわがされてしまう。一方いっぽう,CLOSではそのような通常つうじょう上書うわがき(オーバーライド)戦略せんりゃくだけにとどまらず、多種たしゅ多様たよう戦略せんりゃくがANSI標準ひょうじゅん定義ていぎされ、かつ自由じゆう定義ていぎできる。 (ただし、javaはsuperという特殊とくしゅなメソッドをそなえているため、クラスのメソッドからおやのメソッドをぶことができ、言語げんご柔軟じゅうなんせいたかめている。)

メソッド結合けつごう法則ほうそく総称そうしょう関数かんすう定義ていぎごとに指定していする。標準ひょうじゅんメソッド結合けつごう以外いがいのメソッド結合けつごう法則ほうそく指定していした場合ばあい、メソッド定義ていぎさいにはメソッド指定してい(Qualifier)指定していして、結合けつごう法則ほうそく固有こゆう機能きのう使つかうことを指定していしなくてはいけない。それぞれのメソッド結合けつごう複数ふくすうのメソッド指定していつ。なお、すべてのメソッド結合けつごう:aroundメソッド結合けつごうたなくてはならないと定義ていぎされている。

standard メソッドコンビネーション / 標準ひょうじゅんメソッド結合けつごう

[編集へんしゅう]

これはjavaのもつ継承けいしょう戦略せんりゃく共通きょうつうてんがある。標準ひょうじゅんメソッド結合けつごうでは、指定してい指定していしない( unspecified method qualifier )メソッドのことをプライマリ・メソッド ( Primary method )とび、これには上書うわが戦略せんりゃくもちいる。また、そのに:around,:before,:afterメソッド結合けつごうつ。

メソッド定義ていぎなかでは、(call-next-method)という特殊とくしゅ関数かんすうぶことができ、これはつぎ適用てきようすべきメソッドをす。このページの上部じょうぶに、この関係かんけいしるしたがある。

+ メソッド結合けつごう

[編集へんしゅう]

これは、すべての適用てきよう可能かのうメソッドを実行じっこうし、それらのかえしたわせて全体ぜんたいとしてかえすという結合けつごう方法ほうほうである。同様どうようのメソッド結合けつごうとして標準ひょうじゅん定義ていぎされているものに、list,progn,appendなどがある。

max メソッド結合けつごう

[編集へんしゅう]

これは、すべての適用てきよう可能かのうメソッドを実行じっこうし、それらのかえした最大さいだい全体ぜんたいとしてかえすという結合けつごう方法ほうほうである。 同様どうようのメソッド結合けつごうとして標準ひょうじゅん定義ていぎされているものにminがある。

あらたなメソッド結合けつごう定義ていぎ

[編集へんしゅう]

define-method-combination[6]は、ユーザーに、あらたなメソッド結合けつごう定義ていぎする自由じゆうあたえる。

以下いかに、CLOSをもちいて複数ふくすうのクラスでメソッドを適用てきようするれいしめす.

クラス定義ていぎ

[編集へんしゅう]

動物どうぶつ野生やせいいぬ、ペットのいぬ人間にんげん、ステュワーデス、おとこというクラスを定義ていぎした。

(defclass animal ()
  ((sex :reader sex-of :initarg :sex)))
;; 初期しょき設定せっていするためのキーワード引数ひきすうを :sex に指定していする

(defclass named-mixin ()
  ((name :type string :reader name-of :initarg :name)))
;; 名前なまえつオブジェクトのmixin
;; :reader 指定していにより、スロットよう関数かんすう自動じどう定義ていぎされる

(defclass wild-dog (animal)
  ((food :initform :anything)))
(defclass pet-dog (animal named-mixin)
  ((food :initform :dog-food)))
;; :initformにより、インスタンス作成さくせい設定せっていしない場合ばあい初期しょきさだめる

(defclass person (animal named-mixin)
  ((address :accessor adress-of)))
;; accessor指定していにより、両方りょうほう関数かんすうつくられる

(defclass male-mixin ()
  ((sex :initform :male)))
(defclass female-mixin ()
  ((sex :initform :female)))
(defclass stewardess (person female-mixin)
  ())

スタンダード・メソッドコンビネーション

[編集へんしゅう]

それぞれの継承けいしょうじゅんもとづいて、なにかをわせてみる。

(defun say (sound)
  (format t sound))
;; 標準ひょうじゅん出力しゅつりょく

(defgeneric saysomething (animal))

(defmethod saysomething ((ani animal))
  (say "aaaaa!"))
;; 通常つうじょう動作どうさ継承けいしょうにより上書うわがきされる

(defmethod saysomething :before ((p person))
  (say "hi!"))
;; :before 指定していにより、子孫しそんクラスのメソッドをあとにつづいて実行じっこうできる

(defmethod saysomething ((st stewardess))
  (say "welcome aboard!"))
;; stewardess は person クラスを継承けいしょうするので、:before 指定していしたが
;;  hi! とったのちに welcome aboard! という

list メソッドコンビネーション

[編集へんしゅう]

多重たじゅうディスパッチとlistメソッドコンビネーションをもちいて、なにかがなにかに出会であったとき反応はんのうをリストにしてさせてみる。

(defgeneric reaction (of to)
  (:method-combination :list))
;; だいいち引数ひきすうがとるだい引数ひきすうへの反応はんのうかえす。
;; メソッド結合けつごうをstandardからlistへ変更へんこうする。
;; そのため、それぞれのメソッドのがえがlistにまとめられてかえ


(defmethod reaction list ((a1 animal) (a2 animal))
  :look)

(defmethod reaction list ((a1 wild-dog) (a2 wild-dog))
  (if (in-same-group a1 a2)
	  :sniff  ;; くんくん
	  :bark)) ;; える

(defmethod reaction list ((wild wild-dog) (pet pet-dog))
  :bark-strongly)
(defmethod reaction list ((pet pet-dog) (wild wild-dog))
  :run-away)

(defmethod reaction list ((pet pet-dog) (p person))
  :escort)

(defmethod reaction list ((p person) (pet pet-dog))
  :go-for-a-walk)

(defmethod reaction list ((p1 person) (p2 person))
  :greetings)

(defmethod reaction list ((st stewardess) (p person))
  :welcome-aboard)

(defmethod reaction list ((f1 female-mixin) (p person))
  :watch-clothes)

(defmethod reaction list ((m male-mixin) (f female-mixin))
  :watch-hip-tits-and-waist)

(reaction (make-instance 'animal)
	  (make-instance 'animal))
;; --> (:LOOK)


(reaction (make-instance 'man)
	  (make-instance 'stewardess))
;; --> (:GREETINGS :LOOK :WATCH-HIP-TITS-AND-WAIST)


(reaction (make-instance 'stewardess)
	  (make-instance 'man))
;; --> (:WELCOME-ABOARD :GREETINGS :LOOK :WATCH-CLOTHES)


(reaction (make-instance 'wild-dog)
	  (make-instance 'man))
;; --> (:LOOK)

(reaction (make-instance 'pet-dog)
		  (make-instance 'man))
;; --> (:ESCORT :LOOK)


(reaction (make-instance 'pet-dog)
	  (make-instance 'wild-dog))
;; --> (:RUN-AWAY :LOOK)

参考さんこう文献ぶんけん

[編集へんしゅう]
  • "CommonLoops: merging Lisp and object-oriented programming", by Daniel G. Bobrow, Kenneth Kahn, Gregor Kiczales, Larry Masinter, Mark Stefik, Frank Zdybel. 1986, Portland, Oregon, United States. Pages 17 - 29 of the Conference on Object Oriented Programming Systems Languages and Applications, ISSN 0362-1340.
  • "A History and Description of CLOS", by Jim Veitch. Pages 107-158 of Handbook of Programming Languages, Volume IV: Functional and Logic Programming Languages, ed. Peter H. Salus. 1998 (1st edition), Macmillian Technical Publishing; ISBN 1-57870-011-6
  • Gregor Kiczales, Jim des Rivieres, and Daniel G. Bobrow, The Art of the Metaobject Protocol, 1991, MIT Press. ISBN 0-262-61074-4
  • Sonya Keene, Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS, 1988, Addison-Wesley. ISBN 0-201-17589-4.

脚注きゃくちゅう

[編集へんしゅう]
  1. ^ 「CLOS は標準ひょうじゅん規格きかくである。複数ふくすうのベンダーがCLOSを提供ていきょうしている。CLOS やその一部いちぶのLISPけい言語げんごである EuLisp や EmacsLisp にオブジェクト指向しこう導入どうにゅうするのに使つかわれている」 p. 110 (Veitch 1998)
  2. ^ p. 108 (Veitch 1998)
  3. ^ http://www.cliki.net/Current%20recommended%20libraries
  4. ^ ただし、このオプションはdefgeneric:argument-precedence-orderというオプションによって逆順ぎゃくじゅん変更へんこうできる。
  5. ^ http://www.lispworks.com/documentation/HyperSpec/Body/07_ffab.htm
  6. ^ http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm#define-method-combination

外部がいぶリンク

[編集へんしゅう]