สงสัยการเขียน php แบบ oop เรื่อง overloading override ครับ
คับ ซื้บทอด implement abstract method, override
เมธอดชื่อเดียวกันอาจทำงานไม่เหมือนกันก็ได้เช่น นกบิน กระพือปีก เครื่องบินไม่ขยับปีกแต่มีใบพัดหมุน
หรือ อินเตอร์เฟสติดต่อฐานข้อมูลแต่ละยี่ห้อ มี interface มาให้ ให้อิมพลีเมนต์แต่ละยี่ห้อเอง มีเมธอดชื่อเหมือนกัน แต่ทำงานภายในไม่เหมือนกัน
ประวัติการแก้ไข 2013-07-30 18:59:00 2013-07-30 19:00:32
Date :
2013-07-30 18:56:41
By :
pjgunner.com
overide กับ implement คนละอันนะครับ แต่มันก็เรื่องเดียวกัน
แปลตรงตัว Polymorphisms
Date :
2013-07-30 19:26:51
By :
pjgunner.com
เนื่องจาก PHP ไม่มีการกำหนด return type และไม่มีแม้แต่กำหนดชนิดตัวแปร มีแค่ type hint เท่านั้น
type hint คือ การบอกว่าฟังก์ชั่นหรือ method ต้องการตัวแปรชนิดใด
ซึ่งมีแค่ array และ ชื่อคลาส เท่านั้นที่เป็น type hint ได้ (scalar ไม่ได้)
array type hint
function test(array $arr) {
print_r($arr);
}
test(array(1, 2, 3)); // OK
test(555); // Fatal Error
PHP ไม่มี scalar type hint ดังนั้น string ใน type hint จะไม่ได้หมายถึงชนิด string แต่จะหมายถึง Class string
<?php
function test(string $str) {
echo $str;
}
test('Hello World'); // Fatal Error
object จะไม่ได้หมายถึงชนิด object แต่จะหมายถึง Class object
<?php
function test(object $obj) {
print_r($obj);
}
$o = new stdClass;
test($o); // Fatal Error
แบบนี้ OK
<?php
class object
{
}
function test(object $obj) {
print_r($obj);
}
$o = new object;
test($o); // OK
สรุปว่า type hint ใน PHP นอกจาก array ที่ให้ความหมายตรงตัว (คือ array จริงๆ) นอกนั้นจะเป็นชื่อ Class ทั้งหมด
override ในระบบ class ของ PHP มีแค่สองอย่างที่ strict คือจำนวน argument ใน argument list และ type hint ครับ
แม้ method test() ใน B จะมีชื่อตัวแปรไม่เหมือนกัน ก็โอเค
<?php
class A
{
public function test($a)
{
}
}
class B extends A
{
public function test($b)
{
}
}
$b = new B();
แต่ถ้ามี type hint จะต้องตรงกัน แบบนี้จะเกิด error
<?php
class A
{
public function test($a)
{
}
}
class B extends A
{
public function test(array $a)
{
}
}
$b = new B();
Date :
2013-07-31 09:16:34
By :
cookiephp
ผมจำได้ละ ไม่ได้เขียนโปรแกรมนานลืมหมด
overload ก็คือ เมธอดชื่อเดียวแต่รับหลายพารามิเตอร์ และอาจมีการทำงานต่างกันได้ ปรกติใช้ในภาษา static เช่นจาว่า เช่น
public void xyz(String a, double b)
public void xyz(String a, double b, AAA c)
แต่ใน php เราจะใช้วิธีการ เขียนเมธอดเดียว แต่เช็ค argrument เอา ด้วย func_num_args(), func_get_args() พวกนี้หรือใช้ default value
ซึ่งจริงๆแล้ว Polymorphism ไม่ใช่การทำ overloading แต่เป้าหมายคล้ายกัน(ใน php จริงๆ ใช้เมธอดเดียวแต่สามารถส่งพารามิเตอร์ได้หลายแบบ แต่ภาษา static เช่น java มันต้องเขียนหลายเมธอดชื่อเดียวกันแต่ละแบบตามพารามิเตอร์ที่ต้องการ)
ส่วน override จริงๆ ใน php ไม่ต้องการหรืออาจทำไม่ได้ เพราะ php แต่ก่อน ไม่ได้บังคับ type ได้ อย่างคลาสที่ไม่ได้สืบทอดคุณสมบัติมาแต่มีเมธอดชื่อเดียวกันก็ทำงานได้ แต่ตอนนี้มี type hinting (อย่าง java ทำ Polymorphism ได้แม้แต่ใน Array ex. Mom a[] อาเรย์ที่เก็บเฉพาะคลาส Mom กับลูกหลาน)
ตัวอย่าง override โดยใช้ type hint
Code (PHP)
class Mom{
public function test(){echo 'mom';}
}
class A extends Mom{
public function test(){echo 'a';}
}
class B {
public function test(){echo 'b';}
}
class C{
public function __construct(Mom $arg1){
$arg1->test();
}
}
$arr = array(new Mom, new A, new B);
new C($arr[0]);
new C($arr[1]);
new C($arr[2]); // error
// รวมถึง class property ที่เป็น public
ประวัติการแก้ไข 2013-07-31 09:46:22 2013-07-31 09:48:16 2013-07-31 09:49:04 2013-07-31 09:52:35 2013-07-31 10:05:40 2013-07-31 10:06:52
Date :
2013-07-31 09:42:28
By :
pjgunner.com
พอเห็นที่คุณเอี่ยวตอบก็นึกได้ว่าที่ผมตอบไปข้างบนไม่ถูกต้องเสียทีเดียว
override ในระบบ class ของ PHP มีแค่สองอย่างที่ strict คือจำนวน argument ใน argument list และ type hint ครับ
ยกเว้น contructor ที่ไม่ต้องมีจำนวน argument และ type hint เหมือนคลาสแม่ครับ
Code (PHP)
<?php
class A
{
public function __construct($a, $b, $c)
{
echo "$a,$b,$c";
}
public function test($a)
{
echo $a;
}
}
class B extends A
{
public function __construct($x)
{
parent::__construct($x, 2, 3);
}
public function test($a)
{
echo $a * $a;
}
}
Date :
2013-07-31 10:28:16
By :
cookiephp
ผมก็รู้อยู่ว่า overide constructor ไม่ต้องทำพารามิเตอร์เท่ากัน
กำผมนึกว่า ทำ constructor ใน php แบบ overload หลายๆ คอนสตรัคเตอร์ได้ในคลาสเดียวได้ แต่กลับทำคอนสตรัคเตอร์ได้อันเดียว
ไม่แน่ใจว่า __function อื่นๆ นี่ทำหลายพารามิเตอร์แบบ extend overload ได้มั้ย
ขอตั้งชื่อแบบมั่วๆ extend overload เพราะ สามารถเรียก ทั้งแบบ 1 หรือ 3 พารามิเตอร์ก็ได้
php ปวดหมอง
ไม่แน่ใจว่า __function อื่นๆ จะทำ extend overload ได้เหมือนกัน
ไม่ค่อยได้ใช้ oop หรือคุณสมบัติที่ static lang ต้องมีแต่ php เป็น dynamic ไม่ต้องมีก็ได้ หรือมีแล้วใช้หรือไม่ใช้ก็ได้ อย่าง polymophism ที่เป็นการบังคับ type
ประวัติการแก้ไข 2013-07-31 11:05:48 2013-07-31 11:08:56 2013-07-31 11:10:35
Date :
2013-07-31 11:04:59
By :
pjgunner.com
เห็นคนอื่นเค้าเขียนเสริมกัน ขอเขียนมั้ง
ใน php ถ้าจะใช้ property หรือทำ overload method นั้น
อย่างที่บอกไปข้างบน คือ มันทำได้ แต่ต้องทำแบบอ้อมๆ เอา
ไม่มีโค้ดการเขียนแบบตรงๆ เหมือนภาษา oop ทั่วไป
โดยใช้ megic method ช่วย กล่าวคือ ความจริงมันไม่มีชื่อ property หรือ method
นั้นจริงๆ หรอก เราจะอาศัยการเรียกผ่าน megic method __get __set __call __callStatic เอา
ซึ่งเพราะมันไม่มีชื่อจริงๆ ในโค้ดเลยทำให้ ide ต่างๆ ทำ code completion ลำบาก
จะ debug ลำบากด้วยหรือเปล่าตอบไม่ได้ เราเขียนโปรแกรมเล็กๆ เล่น ลองโค้ดเฉยๆ
แต่ที่แน่ๆ โค้ดเราดูสวยขึ้น ในมุมมองของคนใช้ oop นะ บางอย่างใจมันคิดไว้ว่ามันควรจะเป็น
property ก็ต้องเขียนด้วย property ถ้ามีแค่ method (function) ให้ใช้ มันรู้สึกขัดใจยังไงชอบกล
** ความเห็นส่วนตัวนะ
properties.php
<?php
namespace jquery\ui\base;
class properties {
public function __set($property, $value) {
if (property_exists($this, 'property_'.$property)) {
$property_name = 'property_'.$property;
$this->$property_name = $value;
} else if (property_exists($this, 'setonly_'.$property)) {
$setonly_name = 'setonly_'.$property;
$this->$setonly_name = $value;
}
}
public function __get($property) {
if (property_exists($this, 'property_'.$property)) {
$property_name = 'property_'.$property;
return $this->$property_name;
} else if (property_exists($this, 'getonly_'.$property)) {
$getonly_name = 'getonly_'.$property;
return $this->$getonly_name;
}
}
}
?>
calendar.php
<?php
namespace jquery\ui;
spl_autoload_extensions('.php');
spl_autoload_register();
use jquery\phpclass\write as write;
use jquery\ui\base\properties as properties;
class calendar extends properties {
protected $_control_id;
protected $property_ajax = FALSE;
protected $property_target = FALSE;
public function __construct($control_id) {
$this->_control_id = $control_id;
}
public function create() {
write::line();
write::formatln('<!-- ? -->', array($this->_control_id));
write::line('<script type="text/javascript">');
write::line('$(function() {', 1);
write::formatln('$("#?_main").datepicker({', array($this->_control_id), 2);
write::line('dateFormat: "d/m/yy",', 3);
write::line('onSelect: function(date) {', 3);
write::formatln('$("#?").val(date);', array($this->_control_id), 4);
switch ($this->action()) {
case 'JAVASCRIPT':
write::formatln('if ($("#?").is("input"))', array($this->property_target), 4);
write::formatln('$("#?").val(date);', array($this->property_target), 5);
write::line('else', 4);
write::formatln('$("#?").html(date);', array($this->property_target), 5);
break;
case 'AJAX':
write::line('$.ajax({', 4);
write::formatln('url: "?",', array($this->property_ajax), 5);
write::line('type: "POST",', 5);
write::formatln('data: "?=" + $("#?").val(),', array($this->_control_id, $this->_control_id), 5);
write::line('dataType: "html",', 5);
write::line('global: false,', 5);
write::line('async: false,', 5);
write::line('cache: false,', 5);
write::line('success: function(str) {', 5);
write::formatln('if ($("#?").is("input"))', array($this->property_target), 6);
write::formatln('$("#?").val(str);', array($this->property_target), 7);
write::line('else', 6);
write::formatln('$("#?").html(str);', array($this->property_target), 7);
write::line('}', 5);
write::line('});', 4);
break;
default:
write::formatln('$("#" + $("#?").closest("form").attr("id")).submit();', array($this->_control_id), 4);
break;
}
write::line('}', 3);
write::line('});', 2);
write::line('});', 1);
write::line('</script>');
write::line();
write::formatln('<div id="?_main"></div>', array($this->_control_id));
write::formatln('<input type="hidden" id="?" name="?" />', array($this->_control_id, $this->_control_id));
write::formatln('<!-- end ? -->', array($this->_control_id));
write::line();
}
protected function action() {
$result = 'POSTBACK';
if ($this->property_ajax != FALSE)
$result = 'AJAX';
else if ($this->property_target != FALSE)
$result = 'JAVASCRIPT';
return $result;
}
}
?>
Date :
2013-07-31 11:27:48
By :
ห้ามตอบเกินวันละ 2 กระทู้
index.php
<?php
spl_autoload_extensions('.php');
spl_autoload_register();
use jquery\ui as ui;
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Jquery UI</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link type="text/css" rel="stylesheet" href="demos.css" />
<?php ui\script::startup(); ?>
</head>
<body>
<form id="form1" name="form1" method="post">
<div>
<span>แบบ Postback:</span>
<br />
<?php
$calendar1 = new ui\calendar('calendar1');
$calendar1->create();
?>
<span id="result1"><?php if (!empty($_POST)) echo $_POST['calendar1']; ?></span>
<br />
<br />
<span>แบบ Javascript:</span>
<br />
<?php
$calendar2 = new ui\calendar('calendar2');
$calendar2->target = 'result2';
$calendar2->create();
?>
<span id="result2"></span>
<br />
<br />
<span>แบบ Ajax:</span>
<br />
<?php
$calendar3 = new ui\calendar('calendar3');
$calendar3->ajax = 'ajax.php';
$calendar3->target = 'result3';
$calendar3->create();
?>
<span id="result3"></span>
</div>
</form>
</body>
</html>
Date :
2013-07-31 11:32:44
By :
ห้ามตอบเกินวันละ 2 กระทู้
เป็นแบบฝึกหัด php ของเรา
อยากลอง oop เต็มๆ แบบ php ดู
ใช้ namespace ซึ่งนอกจากจะช่วยเรื่อง group ของ class แล้ว
ผลพลอยได้คือสามารถใช้ autoload class โดยไม่ต้องใช้ include อีกด้วย
อยากใช้ class ไหนก็สั่ง use namespace/class (คล้ายๆ import ใน java) เอา
มันก็จะโหลด class นั้นให้ แต่ชื่อ namespace
ต้องสัมพันธ์กับชื่อ folder ที่เขียน class นั้นไว้นะ
Date :
2013-08-01 08:12:45
By :
ห้ามตอบเกินวันละ 2 กระทู้
โอยมึน ลืมไปหมดแล้ว
Date :
2013-08-01 08:58:13
By :
Dragons_first
class properties น่าสนใจดีครับ
Date :
2013-08-01 13:11:16
By :
{Cyberman}
Load balance : Server 00