ComBioLaw.De » Blog » เขียนโปรแกรม » Using Mix-ins with PHP
Using Mix-ins with PHP
ทางแก้ที่โปรแกรมเมอร์มืออาชีพเขาแนะนำกัน คือการใช้งาน Mix-ins แต่อย่าเพิ่งเข้าใจผิดนะครับ ว่า PHP สนับสนุน Mix-ins การใช้งาน Mix-ins ใน PHP ต้องมีการแฮกกันเล็กน้อยถึงจะสามารถใช้งานได้ ซึ่งต่างจาก Ruby หรือ Python การใช้งาน Mix-ins ที่ผมจะเขียนถึงนี้ ผมเอามาจากเวบของ Ivo Jansch อีกทีครับ Mix-ins เป็นวิธีการยืม method ของคลาสอื่นมาใช้ ซึ่งต่างจาก multi inheritance ตรงที่คลาสที่ยืม กับคลาสที่ถูกยืม ไม่ได้มีความสัมพันธ์กับแบบ subclass - superclass ต่างจาก interface ตรงที่ interface กำหนดเพียงแค่ชื่อ method เท่านั้น ส่วนเนื้อใน method ก็ต้องไปกำหนดเองอีกที และต่างจาก method decoration ตรงที่ method decoration ไม่ต้องมีการสร้างคลาส โดยส่วนตัว ผมชอบ method decoration มากที่สุด แต่ PHP มันทำไม่ได้ แกนหลักของ Mix-ins ที่ผมจะเขียนถึงคือ การใช้ method ที่มีชื่อว่า __call ซึ่งทุกคลาสใน PHP จะมี method ชื่อนี้อยู่ ... |
|
|
โดยเมโธท __call เป็นเมโธทประเภท "magic method intercepts" ซึ่งจะถูกเรียก เวลาที่เมโธทของออพเจคถูกเรียก แล้วเมโธทดังกล่าวไม่ได้มีอยู่จริง ซึ่งในกรณีของ Mix-ins นี้ เมโธทของคลาสที่ถูกยืมเมโธทจะถูกเรียกแทน ดังนั้น ปัญหาที่ว่า จะเรียกเมโธทไหนดี หากมีเมโธทที่มีชื่อซ้ำกัน ซึ่งอาจเกิดขึ้นได้ในกรณีของ multi inheritance ก็จะไม่เกิดขึ้นใน Mix-ins ในการใช้งาน Mix-ins ในขั้นแรก เราต้องสร้างคลาสที่มีความสามารถในการยืมเมโธทขึ้นมาหนึ่งคลาสก่อน จากนั้นก็ให้คลาสอื่น ๆ ที่เราต้องการให้มีความสามารถในการยืมเมโธท inherit คลาสนี้อีกทีหนึ่ง ส่วนคลาสที่ถูกยืมเมโธท ไม่จำเป็นต้องมีความสามารถในการยืมเมโธท และไม่จำเป็นต้องรู้อะไรเกี่ยวกับ Mix-ins ซึ่งคลาสที่มีความสามารถในการยืมเมโธท จะมีหน้าตาประมาณนี้
<?php /// @file /// Generic base class for all objects that want to make use of /// mixin functionality. /// /// @author Ivo Jansch <http://www.jansch.nl/2006/08/23/mixins-in-php/> // bow_der_kleine : I guest, this class is a public domain. /// Generic base class for all objects that want to make use of /// mixin functionality class Mixinable{ var $mixinlookup = array(); // The constructor takes a look at the mixins, and creates a lookup // array, so upon a method call, we can quickly determine whether the // method was mixed in. function mixinable(){ if (is_array($this->mixins)){ foreach($this->mixins as $mixin){ $methods = get_class_methods($mixin); if (is_array($methods)){ foreach($methods as $method){ $this->mixinlookup[$method] = $mixin; } } } } } // The __call magic method intercepts any method that does not exist // and falls back to one of the mixins if they define the method that is // being called. function __call($method, $args){ if (isset($this->mixinlookup[$method])){ $elems = array(); for ($i=0, $_i=count($args); $i<$_i; $i++){ $elems[] = "$args[$i]"; } eval("$result = ".$this->mixinlookup[$method]."::".$method."(".implode(',',$elems).");"); return $result; } trigger_error('Call to undefined function '.$method, E_USER_WARNING); } } ?>plain code หมายเหตุ คลาส Mixinable เดิมคือคลาส Object ของ Ivo Jansch ที่ผมนำมาปรับปรุงเพิ่มเติม การใช้งาน Mixins ก็ง่าย ๆ ดังนี้ครับ
<?php class Soldier{ function coup(){ echo("I can not coup, because I am a citizen.n"); } } class Citizen{ function elect(){ echo("I am going to elect a delegate.n"); } } class Person extends Mixinable{ var $mixins = array("Citizen", "Soldier"); function say(){ echo("A person has the right to think and say.n"); } } $person = new Person(); $person->say(); $person->elect(); $person->coup(); ?>plain code โดยคลาส Person นั้น inherit ความสามารถการยืมเมโธทมาจากคลาส Mixinable และเดิมทีมีเพียงเมโธท say() เท่านั้น แต่ด้วยการ Mxinins หรือยืมเมโธทมาจาก Citizen และ Soldier ด้วยการกำหนด attribute ที่มีชื่อว่า $mixins ด้วยคำสั่ง
var $mixins = array("Citizen", "Soldier");plain code ทำให้ Person มีเมโธทอื่น ๆ อีกสองเมโธทนั่นคือ elect จาก Citizen และ coup จาก Soldier เพิ่มเติม จะเห็นได้ว่าการใช้งาน Mixins ช่วยให้เรา reuse การใช้งานเมโธทต่าง ๆ ได้ตามที่เราต้องการ แม้กระนั้นก็ตามเมื่อเปรียบเทียบ Mix-ins กับ method decoration ผมคิดว่ายังมีความสามารถบางอย่างที่ Mix-ins ขาดไปได้แก่
|
|
21 Dec 08 | by | tags เขียนโปรแกรม PHP
bow_der_kleine
จริง ๆ OOP มันไม่ยากหรอกครับ ให้มองว่า Object คือ ตัวแปร array แบบนึงก็ไม่ผิดนัก (PHP มันมองอย่างนั้นจริง ๆ) แต่เป็นตัวแปร array ที่มีฟังก์ชันอยู่ข้างใน (method) สมาชิกใน array ก็คือ attribute นั่นเอง และ Class ก็เป็นแม่พิมพ์ ที่กำหนดพฤติกรรมของ Object เรื่องตัวอย่าง ผมนึกว่าจะไม่มีใครสังเกตเสียแล้ว :D |
ก้อนหินรูปหมู
Happy new year 2009 ค่ะ ขอให้คุณ Charly, คุณเช, คุณbow มีความสุขมากๆตลอดไปค่ะ ขอบคุณที่เขียนบทความดีๆให้อ่านค่ะ (ชอบมาอ่านมากค่ะ) ^O^ |
แม้ว่า PHP จะเป็นภาษาเขียนโปรแกรมที่ได้รับความนิยมอย่างมาก ตามความนิยมในตัว Web Application แต่ก็มีความสามารถหลาย ๆ อย่างที่ผมคิดว่า PHP ควรมี แต่กลับไม่มี หนึ่งในนั้นคือ multi inheritance ซึ่งดูเหมือนจะเป็นแฟชั่นแบบหนึ่ง ที่ภาษาเขียนโปรแกรมหลาย ๆ ภาษาไม่สนับสนุน multi inheritance แต่แนะนำให้ใช้ interface แทน ซึ่งจริง ๆ แล้วมันใช้แทนกันได้ไม่ทั้งหมด โดยเฉพาะอย่างยิ่ง ในกรณีที่เราต้องการใช้ algorithm บางอย่างในตัว method การใช้ interface ไม่สามารถช่วยให้เรา reuse การใช้งาน method หรือ algorithm เหล่านี้ได้
บุญชิตฯ
ผมยังเขียนโปรแกรมแบบ Object ไม่เป็นเลยครับ คาดว่า มันคงซับซ้อนเกินไปสำหรับการศึกษาด้วยตนเอง
แต่เอาเฉพาะช่วงที่อ่านโค้ด php เข้าใจบ้าง และรู้สึกว่า ตัวอย่างเจ๋งดี :-D
23 Dec 08