對象的屬性

發表于:2007-05-25來源:作者:點擊數: 標簽:Code模擬屬性對象
模擬對象的屬性 [code:1:4d03e04cdd] ?php //+---------------------------------------------------------------------------+ //|這個文件是pfc項目的一部分。| //|Copyrightc2004廖宇雷。| //|| //|要查看完整的版權信息和許可信息,請查看源代碼中附帶的

模擬對象的屬性

[code:1:4d03e04cdd]
<?php
// +---------------------------------------------------------------------------+
// | 這個文件是 pfc 項目的一部分。                                             |
// | Copyright (c) 2004 廖宇雷。                                               |
// |                                                                           |
// | 要查看完整的版權信息和許可信息,請查看源代碼中附帶的 COPYRIGHT 文件,     |
// | 或者訪問 http://www.dualface.com/ 獲得詳細信息。                          |
// +---------------------------------------------------------------------------+

/**
 * 定義 ObjectProperties 型別
 *
 * @copyright  Copyright (c) 2004 dualface.com
 * @author  廖宇雷 <daut@dualface.com>
 * @version $Id: ObjectProperties.class.php,v 1.1 2004/09/26 17:09:27 dualface Exp $
 * @package pfc
 * @since 3.0
 */

// {{{ constants
/**#@+
 * 屬性訪問規則
 */
/**
 * 只讀屬性
 */
define ('PROP_READONLY', 1);
/**
 * 可讀可寫屬性
 */
define ('PROP_READWRITE', 2);
/**#@-*/
// }}}
 
/**
 * ObjectProperties 型別定義了具有訪問規則控制屬性的對象
 *
 * 所有 ObjectProperties 的繼承類都必須在類定義文件的最后執行 overload (繼承類名稱),否則無法正常工作。
 *
 * @author 廖宇雷 <daut@dualface.com>
 * @package pfc
 * @version 1.0
 */
class ObjectProperties
{
/**
 * 保存所有可用屬性的名稱和訪問規則
 *
 * @aclearcase/" target="_blank" >ccess private
 * @since  1.0
 * @var    array
 */
var $_properties;

/**
 * 保存屬性值
 *
 * @access private
 * @since  1.0
 * @var    array
 */
var $_properties_value;

/**
 * 構造函數
 *
 * @param array $properties 確定可用的屬性及其訪問規則
 *
 * @return ObjectProperties
 *
 * @access public
 * @since  1.0
 */
function ObjectProperties($properties, $value) {
$this->_properties = $properties;
$new_value = array();
foreach ($properties as $prop_name => $prop_rule) {
if (isset($value[$prop_name])) {
$new_value[$prop_name] = $value[$prop_name];
} else {
$new_value[$prop_name] = null;
}
}
$this->_properties_value = $new_value;
}

/**
 * 回調函數,用于獲取屬性值
 *
 * @param string $prop_name 屬性名稱
 * @param mixed $prop_value 保存屬性的值
 *
 * @return boolean 指示是否成功
 *
 * @access public
 * @since  1.0
 */
    function __get($prop_name, &$prop_value) 
    {
        if (isset($this->_properties[$prop_name])) {
            $prop_value = $this->_properties_value[$prop_name];
            return true;
        } else {
            return false;
        }
    }

/**
 * 回調函數,用于設置屬性值
 *
 * @param string $prop_name 屬性名稱
 * @param mixed $prop_value 屬性的值
 *
 * @return boolean 指示是否成功
 *
 * @access public
 * @since  1.0
 */
    function __set($prop_name, $prop_value) 
    {
     if (isset($this->_properties[$prop_name]) && $this->_properties[$prop_name] == PROP_READWRITE) {
     $this->_properties_value[$prop_name] = $prop_value;
     return true;
     }
     return false;
    }
}

overload('ObjectProperties');

?>
[/code:1:4d03e04cdd]


使用的例子:

[code:1:4d03e04cdd]
<?php
// {{{ includes
/**
 * 載入 ObjectProperties 型別定義
 */
require_once ('ObjectProperties.class.php');
// }}}
 
/**
 * User 型別封裝了基本的用戶信息
 *
 * PFC3 使用者可以繼承 User 型別,以獲得對擴展的用戶信息的處理能力。
 *
 * @author 廖宇雷 <daut@dualface.com>
 * @package pfc
 * @version 1.0
 */
class User extends  ObjectProperties 
{
/**
 * 保存基本數據的屬性名
 *
 * @access private
 * @since  1.0
 * @var    array
 */
var $_base_prop_names;

/**
 * 保存擴展數據的屬性名
 *
 * @access private
 * @since  1.0
 * @var    array
 */
var $_extra_prop_names;

/**
 * 構造函數
 *
 * 所有的基本數據都是只讀的,而所有的擴展數據都是可讀可寫的
 *
 * @param array $base_data 用于構造用戶對象的基本數據
 * @param array $extra_data 用于構造用戶對象的擴展數據
 *
 * @return User
 *
 * @access public
 * @since  1.0
 */
function User($base_data, $extra_data) {
$base_prop_names = array('UserId', 'UserName', 'Password', 
'Email', 'PasswordQuestion', 'PasswordAnswer',
'CreationDate', 'LastLogonDate', 'LogonCount',
'LastPasswordChangedDate', 'LastActivitiesDate',
'IsApproved');
$this->_base_prop_names = $base_prop_names;
$properties = array();
foreach ($base_prop_names as $prop_name) {
$properties[$prop_name] = PROP_READONLY;
}

$this->_extra_prop_names = array();
reset($extra_data);
while ($prop_name = key($extra_data)) {
if (!isset($properties[$prop_name])) {
$this->_extra_prop_names[] = $prop_name;
$properties[$prop_name] = PROP_READWRITE;
}
next($extra_data);
}

parent::ObjectProperties($properties, array_merge($extra_data, $base_data));
}
}

overload('User');
?>


<?php

require_once ('User.class.php');

$base_data = array('UserId' => 123);
$extra_data = array();
$user =& new User($base_data, $extra_data);

echo $user->UserId;
$user->UserId = 1;

$user2 =& new User($base_data, $extra_data);

echo $user2->UserId;

?>
[/code:1:4d03e04cdd]

 dualface 回復于:2004-09-27 22:51:11
傷心啊,都沒人發言

 numlock 回復于:2004-09-28 09:24:57
先說一下設計動機!也許看的人會更多!

 飛雪恨水 回復于:2004-09-28 09:55:00
看的有點糊涂
/ +---------------------------------------------------------------------------+ 
// | 這個文件是 pfc 項目的一部分。                                             | 
// | Copyright (c) 2004 廖宇雷。                                               | 
// |                                                                           | 
// | 要查看完整的版權信息和許可信息,請查看源代碼中附帶的 COPYRIGHT 文件,     | 
// | 或者訪問 http://www.dualface.com/ 獲得詳細信息。                          | 
// +---------------------------------------------------------------------------+ 

/** 
* 定義 ObjectProperties 型別 

* @copyright    Copyright (c) 2004 dualface.com 
* @author       廖宇雷 <daut@dualface.com> 
* @version      $Id: ObjectProperties.class.php,v 1.1 2004/09/26 17:09:27 dualface Exp $ 
* @package      pfc 
* @since      3.0 
*/ 
你上面的注釋 是用程序生成的還是自己 * * 寫的?

 dualface 回復于:2004-09-28 09:58:00
[quote:dedb19fcd3="飛雪恨水"]看的有點糊涂..........[/quote:dedb19fcd3]

自己寫的,只是文件的描述信息。

 飛雪恨水 回復于:2004-09-28 10:19:36
我感覺自己寫那些符號很累啊
/*******************************
@*
@*
@*
*/

 dualface 回復于:2004-09-28 10:22:52
用ZDE的模板功能撒。

良好的注釋對于代碼的維護有很好的作用。

 飛雪恨水 回復于:2004-09-28 10:29:00
我用EDITPLUS
這是我的摸版
很簡單
<?php
/*@文件名稱: 
 *@文件描述:
 *@生成日期:
 *@修改日期:
 *@備注:
 **/          




?>

 dualface 回復于:2004-09-28 10:33:21
@文件名稱

這樣的標記不是標準的,文檔生成工具不認識的。

 深空 回復于:2004-09-28 11:36:32
不知道樓主干嘛用哦
PS:關于注釋可以去看看PEAR的文檔規范和phpdoc,嘿嘿

 dualface 回復于:2004-09-28 11:52:52
在 PHP4 中,自定義的對象是沒有屬性的。
我們要么用一個字段來替代屬性,但是無法控制對象的使用者是否能夠修改這些字段的值。
[code:1:1005c9e0a0]
class test
{
var $Value;

function test() {
$this->Value = 100;
}
}

$t = new test();
echo $t->Value;
$t->Value = 200; // 實際上我們根本不希望用戶修改這個字段值。這個字段應該是只讀的。

[/code:1:1005c9e0a0]

如果用函數調用替代屬性,雖然可以實現“只讀屬性的效果”,但對于可讀可寫的屬性來說就要增加相應的讀取函數和寫入函數。

[code:1:1005c9e0a0]
class test2
{
var $_value;

function test2() {
$this->_value = 100;
}

function GetValue() {
return $this->_value;
}

function SetValue($new_value) {
$this->_value = $new_value;
}
}

$t = new test2();
echo $t->GetValue();
$t->SetValue(200);
[/code:1:1005c9e0a0]

這樣總是不直觀,而且代碼也不容易維護。

使用我上面貼出來的代碼就可以實現這樣的效果:

[code:1:1005c9e0a0]
class test3 extends ObjectProperties 
{
function test3() {
$properties = array("Value" => PROP_READONLY);
$value = array("Value" => 100);
parent::ObjectProperties($properties, $value);
}
}

overload("test3");

$t = new test3();
echo $t->Value;
$t->Value = 200; // 此處會導致錯誤

[/code:1:1005c9e0a0]

 dualface 回復于:2004-09-28 22:51:55
[b:dbc1e57bd2]這一切看上去很美![/b:dbc1e57bd2]

很不幸,這種方式有幾個嚴重的缺陷
1、由于采用了 overload() 提供的重載機制模擬對象的屬性,因此訪問對象的屬性時實際上就會調用該對象的 __get() 或者 __set() 函數。如果進行大量這樣的屬性訪問操作,效率毫無疑問比使用成員變量低得多。

2、也許 PHP4 的 overload() 設計上有一些缺陷。當我們試圖將一個 overload 化了(也就是對該型別調用了 overload() 函數)的對象的【引用】賦值給另一個 overload 化對象的成員變量時,PHP4 會報告錯誤。
[code:1:dbc1e57bd2]
<?php

class test3
{
function __get() {...}; // 這里是簡化后的代碼
function __set() {...};
}

overload('test3');

class test4
{
function __get() {...};
function __set() {...};

var $_x;
function dosomething(& $obj) {
$this->_x =& $obj; // 這里會報錯,如果去掉 & 就可以運行了
}
}

overload('test4');

?>
[/code:1:dbc1e57bd2]

3、此外,如果在多重繼承中應用 overload(),會導致 PHP 運行環境出錯。

看來這種方式也只能作為一個試驗,實際應用還是不行的。至于 PHP5 會不會有后面兩個問題,我沒有測試過。

 HonestQiao 回復于:2004-09-29 14:26:26
首先,你沒有提前給出設計文檔,所以看你的這個東西比較模模糊糊

 longnetpro 回復于:2004-09-29 17:42:05
[quote:3a9a5ad0df="dualface"]
這一切看上去很美! 

很不幸,這種方式有幾個嚴重的缺陷: 
1、由于采用了 overload() 提供的重載機制模擬對象的屬性,因此訪問對象的屬性時實際上就會調用該對象的 __get() 或者 __set() 函數。如果進行大量這樣的屬性訪問操作,效率毫無疑問比使用成員變量低得多。 

2、也許 PHP4 的 overload() 設計上有一些缺陷。當我們試圖將一個 overload 化了(也就是對該型別調用了 overload() 函數)的對象的【引用】賦值給另一個 overload 化對象的成員變量時,PHP4 會報告錯誤

3、此外,如果在多重繼承中應用 overload(),會導致 PHP 運行環境出錯。

看來這種方式也只能作為一個試驗,實際應用還是不行的。至于 PHP5 會不會有后面兩個問題,我沒有測試過。[/quote:3a9a5ad0df]

對樓主表示欽佩!能做出這樣的總結。

本來昨天想發一長篇來潑樓主一大盆冷水的,不過又覺得花的時間太多不好,且深更半夜想問題比較模糊,只想到三點問題,總算輕輕放過了。今天有點精神,深夜再寫。

今天看樓主自我批評,方發覺樓主果然分析問題透徹!一語就道破昨天我想寫的第一個問題。用__set及__get函數重載我是不贊成的,因為它們將攔截所有對對象屬性的操作,不論是你否預先定義過,一方面增加了已存在屬性處理時的復雜度,二是大大增加了對非指定屬性處理的復雜度,比用直接的setXXX或getXXX的調用還要復雜。不但對屬性要進行各種判斷,還要倒一手進到一個數組,這種方式用到一個具體的類里面完全是得不償失,資源浪費加大多倍。我的意見是凡沒有特殊的必須的要求,不要輕易用重載。

而我想說的第二點是如果樓主因為想實現屬性的限制存取而用重載,則根本沒有這個必要。說無必要有兩點,一是沒有必要用這個方法;二是連這個限制都沒有必要。第一點無必要是基于第二點的,如果連限制都沒有必要,那就更沒有這個必要去實現它了。為什么沒有必要限制呢?因為沒有人會故意改那些本來要用函數來改的屬性。一般來說,你只提供類庫,你給使用者或是二次開發者的只是接口,根本不必涉及到內部的成員變量——如果你的類設計得足夠好。而屬性這個東西在OO里的本義與樓主說的是不同的,它只是從控件的某些概念中引申出來的,所謂可讀或可讀寫也是如此。而DELPHI中屬性的概念與OO的概念差不多,只是一些特殊變量或是函數按一定規則組合起來的一種機制的簡單化,而并非只指單個變量,對屬性的讀寫,不僅僅是對某個變量進行讀寫,而是一組操作過程。這個過程有簡單有復雜,最簡單的一種就是對單個變量進行讀寫,這個變量本身在作用域內是可讀寫的,但操作規則如果規定只能用某種方式對該變量進行讀操作,而禁止任何方式對它進行寫操作,那么從規則上,就只能讀取該變量的值,將這組操作定義為一個屬性,這個屬性就是只讀的。在Delphi或VB中,屬性全是公共的,而變量則全是私有的。在JAVA與C++中則沒有明確的屬性這個概念。在PHP4中之所以說沒有必要,因為PHP4的成員變量全是公共的,根本無法限制其作用域,它可以在任何時間任何地點被讀寫,因此限制它純屬多余。那在PHP5中有作用域的限制,是否有必要呢?那么就請看第三點。

第三點,在PHP5中也沒有必要。因為PHP5完全可以用JAVA或C++的方式來對成員變量進行讀寫訪問限制,而且在一般情況下,也根本沒有可能動態存取那么多原先未定義的屬性。那么,這樣會不會導致樓主說的不直觀或維護不易呢?也不會。不直觀,樓主的意思是說用$obj->status = 'Middle Class' 比用$obj->setStatus('Middle Class') 來得直觀,其實只是個習慣問題,兩者都直觀。而說到維護問題,相反,是樓主的方法更不易,一方面是因為用樓主的方法處理復雜度增加,二是因為用JAVA或C++方式更容易控制,調試更清楚。唯一的不方便則是第二種方法代碼可能會寫得多一點。

可能還有一些別的什么原因,不過腦子又迷糊了,還是去睡覺好了。

 dualface 回復于:2004-09-29 22:49:55
[quote:562847bba1="longnetpro"]

對樓主表示欽佩!能做出這樣的總結。

本來昨天想發一長篇來潑樓主一大盆冷水的,不過又覺得花的時間太多不好,且深更半夜想問題比較模糊,只想到三點問題,總算輕輕放過了。今天有點精神,深夜再寫。

今天?.........[/quote:562847bba1]

確實如此。感覺有時候是為了OO而OO,應該叫做過度OO吧?呵呵

主要是這段時間都在用 C# 搞開發,所以感覺 .NET 那樣純 OO 的環境確實很爽。

 fzj-w 回復于:2004-11-03 12:31:35
我用Eclipse寫PHP,設置自動生成注釋

<?php
# +----------------------------------------------------------------------+
# | PHP Version 5                                                                  |
# +----------------------------------------------------------------------+
# | Copyright (c) 2004 redundancy code                               |
# +----------------------------------------------------------------------+
# | This source file is subject to version 2.02 of the PHP license,      |
# | that is bundled with this package in the file LICENSE, and is        |
# | available at through the world-wide-web at                           |
# | http://www.php.net/license/2_02.txt.                                 |
# | If you did not receive a copy of the PHP license and are unable to   |
# | obtain it through the world-wide-web, please send a note to          |
# | license@php.net so we can mail you a copy immediately.               |
# +----------------------------------------------------------------------+
# | Authors: redundancy code <redundancycode@gmail.com>                        |
# $Id: test.php,v 0.1 2004-11-3 12:31:21 pajoye Exp $
#

?>

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97