éçå㨠OO ã¨ãããã®ã¯ã¯ããããâ¦
OO ã®æ¹é¢ããããéçåã¨ãå¥ã«å½¹ã«ç«ã¤ã¨ã¯æããªããéçåã®äººã¯é ããããã
ã¨ãé¢æ°åã®æ¹é¢ããããéçåãå½¹ã«ç«ããªããªãã¦ã¯ããªã OO ã®äººã¯é ããããã
ã¨ãè¯ãèããã¦ãããã§ãããダックタイピング心理学 ã¨ãããçã«é ããããæè¦ãç¡è¦ã§ããã¨ããã¨ï¼ç¡è¦ã§ããªãéãããã§ããï¼ãã¾ãç§ã«ã¯ã©ã£ã¡ãããããã§ããªããã¨ãã話ã§ãã
åãã´ãç®±ã«æ¨ã¦ã¦ããã¦ãããå¾ã§ã´ãç®±ãæ¼ããªããåãªãããããªã
ãªãã¸ã§ã¯ãã®éçåã·ã¹ãã ã大éæã«ããã¨ã¾ã upcast 㨠downcast ãããã¾ãã upcast ã¯ãªãã¸ã§ã¯ãã®éçåããããå±ããã¯ã©ã¹ãããã®ã¹ã¼ãã¼ã¯ã©ã¹ã«ãå¤ãã¡ã¾ããã¨ãdowncast ã¯ãã®éããªãã¸ã§ã¯ãã®éçåããããå±ããã¯ã©ã¹ããåã¯ã©ã¹ã«å¤ãã¡ã¾ããã¨ã§ãããµãã¯ã©ã¹ã®ç©ã¯ã¹ã¼ãã¼ã¯ã©ã¹ã¨ãã¦ãéç¨ããã¯ãã§ããã upcast ã¯å¤±æãã¾ããã downcast ã¯å¤±æããå¯è½æ§ãããã¾ãããã®ããã« downcast æã«ã¯æ¬å½ã«ãã®ãªãã¸ã§ã¯ãã¯ãµãã¯ã©ã¹ã®è¦è«ããæ¡ä»¶ãæºããã¦ããã®ããæ¤æ»ããªãã¦ã¯ããã¾ããã
ããã§æ³¨æãã¦æ¬²ããã®ã¯ upcast ããªãã¸ã§ã¯ãã®éçåæ å ±ãç©æ¥µçã«å¿ããè¡çºã ã¨ãããã¨ã§ããããã¦å¤±ãããéçåæ å ±ã¯ downcast æã®ãã¹ãã«ãã£ã¦å復ãããã®ã ããããã¯å¤±æããå¯è½æ§ãããããã£ããå¤ã£ã¦ããåæ å ±ãã´ãç®±ã«æ¨ã¦ã¦ããã¦ãããããã°ã©ã å®è¡æã«ã´ãç®±ãæ¼ã£ã¦ããããã§ããããã¯å¿ä½ç¡ãï¼
ãããæ®å¿µãªãããéçã«å¤ã£ã¦ããåæ å ±ãä¸é¨æ¨ã¦ããã¨ã§æè»ãªãªãã¸ã§ã¯ãæä½ãè¡ããâ¦ããã(éçåã®ãã)ãªãã¸ã§ã¯ãæåã®æ¬è³ªãªã®ã§ãã
è¨èªã®æ¬è³ªã¨ã㦠upcast ãå¿ é ãªéçåä»ããªãã¸ã§ã¯ãæåã§ã¯éçåãå¿ããããªããã£ããèªç±ã«ä½¿ãã¾ããã§ãããåã®å©ç¹ãããã£ã¦ããªããã«ã¤äººãããããè¨èªã使ãã¨ããæ°è»½ã«éçåæ å ±ãæ¨ã¦ã¦ãã¾ãã¾ããããï¼åæ å ±ï¼å¾ã§å¿ è¦ãªã¨ãã« downcast ããã°ãããããªãã§ãããããããã¦å¿ è¦ããªãã´ãç®±ãæ¼ãããã°ã©ã ãèªçããããã ãããã¦ç©¶æ¥µçã«ã¯
ãå ¨é¨ obj ã«ãã¦ãã¾ãã°ããããªã¯ã©ã¹ã«ä½¿ãã¾ããï¼ããã¯å®éãããã³ã¼ãåå©ç¨æ§ã ï¼ã
ã¨ããèã人ãæ³£ãç¬ããããªãåéããå®éã«åºã¦ãã¾ãã¾ãããâ¦ãæå·æ§ã§ãã
çãããç¥ã£ã¦ããã§ããããã©ãã ãéã¯å±ãªãã¨æãèããã¦ã馬鹿ã¯éãããã°æã¡ããããã®ã§ãã ã©ãã ã注æãã¦ã downcast ãããéã downcast ã§ããç´ããå¹ããããªãã§ãããã¨è¨ããªãã馬鹿ã¯ç¡æå³ãª upcast ãç¹°ãè¿ããéãæã¡ã¾ããããã§ããå·»ãè¾¼ã¾ããæ¹ã¯ãã¾ã£ããã®ãããªãããããªãã¨ãããã®ã§ãããã
ãéçåã·ã¹ãã ã¯å½¹ã«ç«ããªãã㨠OO ã®æ¹ããã£ããããããã¦ãããã¯ã¿ã¤ãã³ã°ã«ãã¡ãããªyoï¼ã¨ããã®ç§ã¯æ®éã«ç解ã§ãã¾ããããã¼ã¬ã¼ãæ¦æ³ã§ãã(ã¾ããã£ãããéçºãã¼ã ãå éåå°äººæ°åããã®ã¯æéã®åé¡ã§ããâ¦
éçåã使ã£ã¦ããã®ã«ããããæ°è»½ã«å¿ãã¦ãã¾ããã¨ã®è¨èªæ©è½ã OO ã®æ ¹å¹¹ã¨ãã¦å¿ è¦ã¨ããã¨ããã«ãçç¾ããæ§é ãããããã§ããéçå㨠OO ã¯ã¯ããããä¸æããããããªãããããªãããã¨ãããã¨ã§ããã
OO ã¨éçåã®å¥ã®ä¸çç·
ããã§ä»æ¥ãç´¹ä»ãããã®ã OCaml ã¨ããè¨èªã§ã®ãªãã¸ã§ã¯ãã®éçåã·ã¹ãã ã§ããOCaml ã®ãªãã¸ã§ã¯ãã®éçåä»ãã¯ã¯ã©ã¹ãã¼ã¹ã§ã¯ãªããæ§é çãµãã¿ã¤ãã³ã°ã¨å¼ã°ãããã¾ãç¾^ç¾æ©è²ã£ã¦ãããã¯ã¿ã¤ãã³ã°ã®éçåçããªã®ã§ãããããã¯ãã¾ãããã§ã¯éè¦ã§ã¯ããã¾ããã*1 ãã®ããã°è¨äºã§ç¦ç¹ãå½ã¦ããã®ã¯æ¬¡ã®äºã¤ã§ã:
- Upcast ã¯ã§ããããããæ示çã§ãããã¦ã¼ã¶ã¼ã«åæ å ±ãæ¨ã¦ããããã¨ãæèããã
- ããã¦ãDowncast ã¯â¦â¦â¦ãªã!
ããã§ããDowncast ã¯ç¡ãã®ã§ããã§ããªãã®ã§ããã´ãç®±æ¼ãã¯ããããã¦ãã§ãã¾ãããè¦æ°´çã«å¸°ããããããªé¦¬é¹¿ãªãããã§ã¯ OO ã§ããªããã¨è¨ã人ãããã§ãããããããã downcast ãç¡ãã¨è¨ãäºã¯ downcast 失æããã¨è¨ããã¨ããªããã¢ãã«ãé³´ããã°æããã¾ãã«ãéããªããã°æããããã¨ããªãã®ã§ããåãå²ãåãã ã¨æãã¾ããã
ãã㦠upcast ããå ´åãæ®éã® OO è¨èªããããæ示çã«ãã®å®£è¨ãè¡ããªããã°ããã¾ããã
æ®éã® éçåä»ã OO ã ã¨:
A a; B b; S ss[] = { a, b };
ã¨æ¸ã㨠a 㨠b ã¯é å ss ä¸ã« upcast ããã¦å ¥ããã¨ã«ãªãã¾ããã OCaml ã§ã¯åããããªã³ã¼ãã¯
(* OCaml ã§ã¯ã¯ã©ã¹ã¯å°æåããå§ã¾ããªããã°ãããªãã®ã§ A, B, S ã§ã¯ãªã ca, cb, cs ã¨æ¸ãã¦ãã¾ãããªãå¤æ°ã®ã¹ã³ã¼ãã¨ã¯ã©ã¹åã®ã¹ã³ã¼ãã¯ç¬ç«ãã¦ããã®ã§ new a ã§ãåé¡ããã¾ãã *) let a = new ca let b = new cb let ss = [ (a :> cs); (b :> cs) ]
ã¨æ¸ããªãã¦ã¯ããã¾ããã
let ss : cs list = [ a; b ]
ã¨ããæ¸ãæ¹ã¯ã§ãã¾ããããã®ããã«åé·ã«æ¸ããªããã°ãããªãã®ã¯ãæ¬å½ã¯å¥ã®çç±ããã£ã¦ã®ãã¨ã§ãããã¦ã¦ã¼ã¶ã¼ã« upcast ãæèãããããã§ã¯ãªãã®ã§ãããå¦ãå¿ã§ããã®ãªãã¸ã§ã¯ãã¯ãã㧠upcast ãã¦ããã®ã ãªã俺ã¯ä»ã¾ãã«éçåæ å ±ãæ¨ã¦ã¦ããã®ã ãªãpoint of no return ãªã®ã ãªãã¨ãããã¨ãèªèãããå¹æãããã¾ããéçåãå¿ãããã¨ãã§ãããã§ããããè¦æããã(ããããã®ããã³ãã®éçåã®å¿çå¦ã¨è¨ãã)
ããã¦å¤±ãããéçåæ å ±ãåãæ»ãæ¹æ³ã¯ãªãã®ã§ããã§ããã
let a' = (List.nth ss 0 <: ca) (* Upcast 㯠:> ãªã®ã§ããã Downcast 㯠<: ã«ãã¦ã¿ã¾ãã *) let b' = (List.nth ss 1 <: cb)
ã¿ãããªäºã¯ã§ãã¾ãããã§ããªãã®ã§ããã
ãå ¨é¨ < > (obj ã¿ãããªãã®ã§ã) ã«ãã¦ãã¾ãã°ããããªã¯ã©ã¹ã«ä½¿ãã¾ããã£ï¼ããã¯å®éãããã³ã¼ãåå©ç¨æ§ã ï¼ã
ãããªå¥´ã¯ upcast ã®ãéãã§èªæ» !(ã ã£ã¦ downcast ã§ããªãããã³ã¼ãã®æ¸ããããç¡ã!!)ã ããç§ãã¡ã¯ã¯ã½ã³ã¼ãã«ã¯åºä¼ããªãã¦æ¸ã!!!
Downcast æª! Downcast ç¦æ¢! åçã«ã¯ã©ã¹æ¤æ»ãã¦éçåå復ãã¦ããããã¨ãªãããDowncast å¿ è¦ã ã¨ãããã¨ã¯ãè¨è¨ã«ä½ãééããããã¯ãã ãã©ããã¦ã OO ã§æ¸ããªããªãç¡çã« OO ã«ãã ããå¿ è¦ã¯ãªã!ããã OCaml ã®èãæ¹ã§ãã
ãªã㧠OCaml 使ãã°ã¿ããªè§£æ±ºã§ãã!!ã¨è¨ãã»ã©ãã»ãç§åä¾ãããªããã§ãæ®éã® OO è¨èªã ã¨ã©ãããã°è¯ãã£ããããUpcast + downcast ã¯ã´ãç®±ã«æ¨ã¦ããã®ãã¾ãæ¾ã£ã¦ããããªããã ã¨ããå°»ããåºãããã®ãã¾ãå£ã«å ¥ãããããªããã ã£ã¦ãã£ãããããããè¨ã£ã¦ãã§ãããï¼ãããï¼downcast ã§ããã ãããªããããªã³ã¼ããæ¸ããªããã£ã¦è¨ãä½ããªâ¦
(ããã downcast ãªãã§ã©ããã£ãããããã°ã©ã æ¸ããã®ãã¨ãããã¨ã«ãã®è¨äºã¯è§¦ãã¦ããªãã®ã§ãã®è¨äºã®èªå·±è©ä¾¡ä½ãã§ãã)
ã§ããã¡ãã downcast ç¦æ¢ã¨ãåãå ¥ããããªã人ãããã§ãããããããªäººã«ã¯ãã¯ã OO ã¨éçåã«ã¯ç¡çããããã ãï¼ åçã«ã¯ã©ã¹æ¤æ»ãã¦éçåå復ãã¦ããããã¨ãªãããããã¾ã§ãã¦ç¡çã«éçåã«ãã ããå¿ è¦ã¯ãªããããã¯ã¿ã¤ãã³ã°çèãæ¹ã§ãã
ã©ã¡ãã«ãããã¯äººããããã§ããç§ã OCaml ã¦ã¼ã¶ã¼ã¯åè ã§ããå¾è ã®äººãå± ãã§ããããç§ã¯åè ã人ã«æ¼ãä»ããã»ã©è¥ãè¡æ°çãã§ããªãã®ã§ã
ãããæ¯åãæªããããã¾ã人éåããã¨æ¯åãæªãããã
OCaml ã§ãªãã¡ãã£ã¦ downcast (代æ°çãã¼ã¿åã使ã£ã¦)
(ãªãããã®è¾ºç¬¬ä¸ç¨¿ã§ã¯ã§ãããæ¸ãã¦ããã®ã§æ¸ãç´ãã¾ããããªãã ãåãééãããããã¨ããããããªãã¸ã£ã´ã¥æããã¾ãããã ãªã)
OCaml ã«ã¯ downcast ãããã¾ããã親ã¯ã©ã¹ã« upcast ãããå ã®ã¯ã©ã¹ã«éçåãæ»ãæ¹æ³ãããã¾ãããã§ã¯æ¬å½ã« downcast ã®ãããªãã®ãå¿ è¦ã«ãªã£ããã©ããããããã®ã§ãããã
ãã¨ãã° OCaml ã§éã£ãã¯ã©ã¹ã«å±ãããªãã¸ã§ã¯ããåããªã¹ãã«æ¾ãè¾¼ãã§ããªãã¨ãå ã®éçåãç¶æãããã¨ã¯ã§ããªãã®ãï¼é¢æ°åè¨èª OCaml ã®ä»£æ°çãã¼ã¿åã使ã£ã¦ã¿ã¾ããã:
type t = A of ca | B of cb let ss' = [ A a; B b ] let a' = match List.nth ss' 0 with A a -> a | _ -> assert false let b' = match List.nth ss' 1 with B b -> b | _ -> assert false
ãã®ããã«æ示çã« A 㨠B ã©ã¡ãããã¨ããå t ãä½ã£ã¦ã¿ã°ä»ããã¦ãããã¨ã§å¥ã®ã¯ã©ã¹ã®ãªãã¸ã§ã¯ããä¸ã¤ã®ãªã¹ãã«æ¾ãè¾¼ããã¨ãå¯è½ã§ããå ã®å ca ã cb ã«æ»ãã«ã¯ãã®ã¿ã°ããã§ãã¯ãã¦ããã°ãããããããããã¹ã¼ãã¼ã¯ã©ã¹ã« upcast ãã¦å®è¡æã« downcast ãã¦ãã®ã¨å¤ãããªãããããªãã®ï¼
ãã¼ãã確ãã« ss' ã®å㯠A ã B ãã©ã¡ãããã¨ããåã«ãªããå ã®åããå£åãã¦ãã¾ãã¾ãããããããããããã㯠upcast 㧠cs ã¨ããåã«ãã¦ãã¾ã£ããã®ããæ å ±ã¯å¤±ããã¦ãã¾ããã cs ããã® downcast å ã¨ãã¦ã¯(OCaml ã§ã¯å ã ã§ãã¾ããã) cs ã®ãµãã¯ã©ã¹ãå ¨ã¦åè£ã¨ãªãã¾ããã代æ°çãã¼ã¿åã使ã£ã¦ããã° ca ã cb ãã®äºã¤ã«çµããã¦ããã®ãå¤ãã¾ããã¤ã¶ããå t ããå ã®ãªãã¸ã§ã¯ãã®åãåãæ»ããã¨ãèããã¨ãã ca 㨠cb 以å¤èããå¿ è¦ã¯ç¡ããã¨ãéçã«ä¿éããã¦ãã¾ãã
ãã¡ããæ°ããåãå®ç¾©ããã°ãªããªããåãªãã¸ã§ã¯ãã¯ã¿ã°ã¥ããããã°ãªããªããã¨è¨ãç¹ã§ããã°ã©ã ã¯é·ããªãã¾ããããã«ã¿ã°ã¯ããã®ã³ã¼ããæ¸ããã°ãªããªãããããè¨èªæ§æä¸ãç¡éã« upcast ãè¡ã£ã¦éãæã¡ã¾ããã¨è¨ãã³ã¼ãããã¯ãä½ç¨è¦éããè¯ããå®éè¯ããã¨ãããã¨ã«ãªãã¾ãããããã¡ãã OCaml ã§ãéãç¡éã«æã¡ã¾ãããã¤ã¾ããç¡æå³ã«ã§ãã代æ°åãã¼ã¿åãä½ã£ã¦ãã®ä¸ã«ãªãã¸ã§ã¯ããæ²¡å ¥ããã¾ããæå³ä¸æãªã³ã¼ããæ¸ããªãããã§ã¯ããã¾ããããããã㯠downcast ä¹±çºã®ããã«æ°è»½ã«ã¯ã§ãã¾ããã*2
ãã¦ãã®æ¹æ³ã®ããä¸ã¤ã®åé¡ã¯ããªã¹ã ss' 㯠ss ã¨éã£ã¦ããªãã¸ã§ã¯ãã®ãªã¹ãã§ã¯ãªããä¸æ®µä»£æ°çãã¼ã¿åãæã¾ã£ã t list ã¨ããåã§ãããã¨ã§ããã§ãããã¯ã©ã¹ ss, a, b, ã«å ±éããã¡ã½ãã m ããã®è¦ç´ ã«å¯¾ãã¦å¼ã³åºããã¨ãé¢åã«ãªãã¾ã:
let () = List.iter (fun o -> o#m) ss (* ss ã¯ãªãã¸ã§ã¯ãã®ãªã¹ããªã®ã§ç°¡åã *) let () = List.iter (fun o -> o#m) ss' ããã¯ééã let () = List.iter (function (* ããæ¸ãå¿ è¦ããã⦠*) | A a -> a#m | B b -> b#m) ss'
ããã¯é¢åã§ãããã³ã³ããã«å¥ã®ã¯ã©ã¹ã®å¤ãå
¥ããããå
±éã®ã¡ã½ããã¯å¼ã³åºããããããã«ãã§ãéçåæ
å ±ã¯æ¨ã¦ãããªãâ¦ãã¼ãããããããã¨ã¯ OCaml ã§ã¯é£ããããã¯ã downcast çãªãã¨ããããã¨ããã¨ã©ããã§ç¡çãæ¥ãã¨ãããã¨ã§ããããã
OCaml ã§ãªãã¡ãã£ã¦ downcast (Downcast å ãè¦ãã¦ãã)
ãã㯠http://caml.inria.fr/pub/ml-archives/caml-list/2006/08/aa0a56475494e183aedc4d2431b30646.en.html ã«èª¬æããã¦ãã¾ããDowncast ãããåæ¯ã«ã¡ã¢ãã¼ãã«ãä½ã£ã¦ããªãã¸ã§ã¯ããç»é²ãã¦ãããdowncast ããããªã£ãã Oo.id ã§æ¢ãåºãæ¹æ³ã§ã:
class ['a] memo () = object val tbl : (< >, 'a) Hashtbl.t = Hashtbl.create 107 method add : 'a -> unit = fun o -> Hashtbl.add tbl (o :> < >) o method downcast : 'b. (< .. > as 'b) -> 'a = fun o -> Hashtbl.find tbl (o :> < >) end class cs = object method kuwa = prerr_endline "kuwa" end class ca = object inherit s method x = 1 end class cb = object inherit s method y = 1 end let () = let ca_memo = new memo () in let a = new ca in ca_memo#add a; (* downcast ã§ããããã«ç»é² *) let b = new cb in let ss = [ (a :> cs); (b :> cs) ] in List.iter (fun s -> s#kuwa) ss; let a' = ca_memo#downcast (List.nth ss 0) in Printf.printf "%d\n" a'#x
ããã¯ãå¾ã§åã downcast ãã¦å復ããããªã£ãã¨ãã®ããã«ãdowncast ããåãã¨ã«ç®ããã¼ãã«ãä½ãããã®åã®ãªãã¸ã§ã¯ããäºåç»é²ãã¦ãããã¨ããæ¹æ³ã§ãããªãã¸ã§ã¯ã㯠upcast ãã¦ããã® equality (Oo.id ã¨ãããã®ã§åããã©ããå¤å¥ãã¾ã)ã¯å¤ããã¾ãããã§ããã upcast ãããªãã¸ã§ã¯ãããå ã®ãªãã¸ã§ã¯ãã復å ããã«ã¯ã Oo.id ããã¼ã«ãã¦ã¡ã¢ãã¼ãã«ãæ¢ãã®ã§ããã
ãã¡ããããã¯ãªãã¡ãã£ã¦ãªã®ã§ã weak hashtbl 使ããªãã¨ãªã¼ã¯ããã¨ãããããããã¼ãã«ã«å±±ã»ã©çªã£è¾¼ãã ãé ããªãããã§ããã
ãããã£ã¨æ¨ãé²ã㦠OCaml ã« RTTI ãå ¥ãã¦ãå ¨ã¦ã®ãªãã¸ã§ã¯ã㯠RTTI ãä¿æããã°ã RTTI æ¤æ»ããã° downcast ã§ãããããï¼ã¨ããã®ã¯ãããã§ãããããã³ã¹ãããããä¸ã«ãéãæã¡ã¾ãã馬鹿ãçºçãããã®ã§ç§ã¯ã¤ãã¹ãã
*1:Downcast ããªãã¨ãããç¾å®çã«ãã£ã¦ãããªãçç±ã¨ãã¦ã¯ã©ã¹ãã¼ã¹ã§ã¯ãªãã®ã§ã¯ã©ã¹é層ããã©ãæ¹æ³ãã Downcast ã§ãããã©ããã®å¤æã«ã³ã¹ãããããã¨ããã®ãããã¾ããã©ã
*2:ãã㯠variant (代æ°çãã¼ã¿å)ã§ã¯ãªã polymorphic variant ã使ããã¨ã§ããæããã«ãªãã¾ãããçç¥ãã¾ã