给猪的鼻子插一根葱_PHP

Jun 01, 2016 pm 12:42 PM
object pro 物体

PHP 具备一些动态语言的特征, 但不彻底. 虽然 PHP 的标志是一头大象, 可这头象的鼻子未免太短, 以致经常够不着东西, 反而象猪了. 本文旨在探讨一种使 PHP 更动态化的方法, 主要是模拟 Javascript 的 prototype 继承. 既然是模拟, 就不是真的能使 PHP 动态起来, 只是插上一根葱, 让它装得更"象"一点.

一. 基本操作
通过 Javascript 的 prototype 动态地为对象添加属性, 我们可以这样:

Object.prototype.greeting = 'Hello'
var o = new Object
alert(o.greeting)
ログイン後にコピー

Js 的内置对象 Object 可看作一个"类", 任何 Js "类"都有 prototype 内置对象, 用 PHP 来模拟它可以是:
error_reporting(E_ALL);

class Object
{
     public static $prototype;

     protected function __get($var) {
         if ( isset(self::$prototype->$var) ) {
             return self::$prototype->$var; }}
}
ログイン後にコピー

然后我们可以:
Object::$prototype->greeting = 'Hello';
$o = new Object;
echo $o->greeting; // 输出 Hello
ログイン後にコピー

这里利用了 PHP 的自动转型特性. 在 PHP 中, 我们要声明一个数组, 并不需要先 $var = array() 然后才做 $var[] = some_value, 直接地使用后者就可以得到一个数组; 同样地直接 $object->var 的时候, $object 就被自动定义为 stdClass 对象. 这就解决了在定义类内静态属性时不能声明 public static $prototype = new stdClass 的问题.

在 Js 中给"类"动态添加方法:
Object.prototype.say = function(word) { alert(word) }
o.say('Hi')
ログイン後にコピー

在 PHP 中模拟:
error_reporting(E_ALL);

class Object
{
     public static $prototype;

     protected function __get($var) {
         if ( isset(self::$prototype->$var) ) {
             return self::$prototype->$var; }}

     protected function __call($call, $params) {
         if ( isset(self::$prototype->$call) && is_callable(self::$prototype->$call) ) {
             return call_user_func_array(self::$prototype->$call, $params); }
         else {
             throw new Exception('Call to undefined method: ' . __CLASS__ . "::$call()"); }}
}
ログイン後にコピー

这样, 就可以
Object::$prototype->say = create_function('$word', 'echo $word;');
$o->say('Hi');
ログイン後にコピー

但是 PHP 的 create_function 返回的结果并不等同于 Js 中的 Function 对象, Js 的 Function 对象是一种闭包(closure), 它可以直接调用宿主的属性, 如
Object.prototype.rock = function() { alert(this.oops) }
o.oops = 'Oops'
o.rock()
ログイン後にコピー

但是在 PHP 中我们不可以写
Object::$prototype->rock = create_function('', 'echo $this->oops;');
$o->oops = 'Oops';
$o->rock();
ログイン後にコピー

会报告 Fatal error: Using $this when not in object context, 因为 create_function 返回的是匿名的普通函数, 它没有宿主. 为解决这个问题, 我们需要在参数中传入对象本身, 而且不能使用 $this 变量名做参数, 我们暂时用一个 $caller 的变量名:
Object::$prototype->rock = create_function('$caller', 'echo $caller->oops;');
$o->oops = 'Oops';
$o->rock($o);
ログイン後にコピー

现在可以了, 可是看上去怪怪的, 一点都不像动态语言. 嗯~, 这根葱还是有点短, 还是不"象".

问题来了:
1. 在调用动态方法时需要传递对象本身, 这算哪门子的面向对象?
2. 我们要在代码中使用 $this, 这才象是在面向对象.

解决方法:
1. 重新写一个函数代替 create_function, 在参数部分挤一个参数 $that 进去作为第一个参数, 在 __call 中向匿名函数传递参数时加入对象本身 $this 作为第一参数.
2. 允许在代码中使用 $this, 我们在代替函数中把 $this 换成 $that.

我们给它添加一个 create_method 函数来代替 create_function
function create_method($args, $code) {
     if ( preg_match('/\$that\b/', $args) ) {
         throw new Exception('Using reserved word \'$that\' as argument'); }
     $args = preg_match('/^\s*$/s', $args) ? '$that' : '$that, '. $args;
     $code = preg_replace('/\$this\b/', '$that', $code);
     return create_function($args, $code); }
ログイン後にコピー

$that 作为参数中的"保留字", 当出现在参数部分中将抛出异常.(在 PHP5 的早期暗夜版本中, $that 也曾经是保留字)

相应地, Object 中的 __call 也要作出改动
class Object
{
     public static $prototype;

     protected function __get($var) {
         if ( isset(self::$prototype->$var) ) {
             return self::$prototype->$var; }}

     protected function __call($call, $params) {
         if ( isset(self::$prototype->$call) && is_callable(self::$prototype->$call) ) {
             array_unshift($params, $this); // 这里!
             return call_user_func_array(self::$prototype->$call, $params); }
         else {
             throw new Exception('Call to undefined method: ' . __CLASS__ . "::$call()"); }}
}
ログイン後にコピー

现在我们就可以
Object::$prototype->rock = create_method('', 'echo $this->oops;');
$o->oops = 'Oops';
$o->rock();
ログイン後にコピー





二. 继承
面向对象的一大特征是继承, 继承最大限度地保留代码重用能力. 但如果直接用上例的 Object 类去创建继承类则会出错, 因为
1. 子类继承的静态属性 $prototype 永远属于父类(不管 $prototype 是标量还是列表, 对象更不消说)
2. 如果子类所继承的方法中有 self 关键字, self 会指向父类而非子类
class Object
{
     public static $prototype;

     protected function __get($var) {
         ... }

     protected function __call($call, $params) {
         ... }
}

class Test extends Object
{
}

Test::$prototype->greeting = 'Hello';
print_r(Object::$prototype);
/* outputs
stdClass Object
(
    [greeting] => Hello
)
*/

Test::$prototype->say = create_method('$word', 'echo $word;');
$o = new Object;
$o->say('Hi');
/* outputs
Hi
*/
ログイン後にコピー

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Xiaomi Mi Pad 6とPro、どちらを買う価値がありますか? Xiaomi Mi Pad 6とPro、どちらを買う価値がありますか? Feb 07, 2024 pm 08:36 PM

多くのユーザーは、Xiaomi Mi Pad 6 と Mi Pad 6 のどちらを購入する価値があるのか​​わかりません。構成の観点からは、Pro の上位構成が間違いなく推奨されますが、価格と自分の予算、および製品の位置付けグループが異なれば、グループも異なります。 Xiaomi Mi Pad 6 と Pro、どちらを買う価値がありますか? 回答: パフォーマンスとカメラのバッテリー寿命の両方の点で、Xiaomi Mi Pad 6 Pro の方が優れています。 1. プロセッサー Xiaomi Pad 6: Snapdragon 870 Xiaomi Mi Pad 6 Pro: より強力な第一世代 Snapdragon 8+ プロセッサー 2. バッテリーサイズ Xiaomi Mi Pad 6: 8840mAh、67W 2 回目の充電 Xiaomi Mi Pad 6 Pro: 8600mAh、33W Xiaomi Mi Pad 6 を充電するとバッテリー寿命は長くなりますが、充電は遅くなります。 3. Xiaomi Mi Pad 6で写真を撮る

Xiaomi Mi Band 8proの起動方法 Xiaomi Mi Band 8proの起動方法 Jan 14, 2024 am 08:51 AM

Xiaomi Mi Band 8 を初めて触ったとき、多くのユーザーは電源を入れる方法がわかりません。実際、その方法は非常に簡単です。USB データ ケーブルを見つけて時計を電源に接続するだけです。を押してしばらく充電すると、ボタンを押して電源が入ります。 Xiaomi Mi Band 8proをオンにする方法 1. まず時計を取り付けます。つまり、テーマとストラップを両側に接続します。 2. 初めて時計の電源を入れるときに、充電ケーブルを接続する必要があります。接続方法は時計の下部にあります。 3. 時計が振動して電源がオンになるまで待ってから、携帯電話に接続します。 >>>

iPhone 15 Pro Max と iPhone 14 Pro Max: 両者の比較と違いは何ですか? iPhone 15 Pro Max と iPhone 14 Pro Max: 両者の比較と違いは何ですか? Sep 19, 2023 pm 08:29 PM

iPhone 15 Pro と iPhone 14 Pro: スペックの比較 iPhone 15 Pro Max と iPhone 14 Pro Max のスペック比較は次のとおりです: iPhone 15 Pro Max iPhone 14 Pro Max ディスプレイサイズ 6.7 インチ 6.7 インチ ディスプレイテクノロジー Super Retina 2,000 nit 寸法 6.29x3 0.02x0.32 インチ 6.33x3.06x0.31 インチ 重量 221 グラム 240 グラム

PHP の json_encode() 関数を使用して配列またはオブジェクトを JSON 文字列に変換する PHP の json_encode() 関数を使用して配列またはオブジェクトを JSON 文字列に変換する Nov 03, 2023 pm 03:30 PM

JSON (JavaScriptObjectNotation) は、Web アプリケーション間のデータ交換の一般的な形式となっている軽量のデータ交換形式です。 PHP の json_encode() 関数は、配列またはオブジェクトを JSON 文字列に変換できます。この記事では、PHPのjson_encode()関数の構文、パラメータ、戻り値、具体的な例などの使い方を紹介します。構文 json_encode() 関数の構文は次のとおりです。

MacBook AirとProの違い MacBook AirとProの違い Feb 08, 2024 am 09:57 AM

MacBook Air は Apple のノートブック コンピュータです。多くのユーザーは MacBook Air と Pro の違いに興味があります。これら 2 つのノートブックには、プロセッサ コア、メイン周波数、グラフィックス カードの種類の点でいくつかの違いがあります。 MacBook Air と Pro の違い: 1. 異なるプロセッサコアとスレッド: MacBook Air のプロセッサはデュアルコアと 4 つのスレッドを備えています。 Pro は MacBook Air よりも強力で、4 つのコアと 8 つのスレッドを備えています。 2. プロセッサのメイン周波数は異なります。MacBook Air のプロセッサのメイン周波数は 1.6 GHz です。 Proのプロセッサの主な周波数は1.4GHzで、MacBook Airの周波数よりわずかに低いです。 3. さまざまなグラフィックカード: macbookair が採用

20 倍ズームを備えた 3 台のカメラ、Honor が Xiaopai Smart Camera Pro を選択 イノベーションが到来 20 倍ズームを備えた 3 台のカメラ、Honor が Xiaopai Smart Camera Pro を選択 イノベーションが到来 Aug 23, 2024 pm 09:44 PM

あなたの家にカメラを設置しましたか?近年、家庭用カメラ製品がにわかにヒットしています。周りの友達に聞いてみると、どこの家にも一台はあるし、複数持っている家もあるそうです。しかし、この製品の人気に伴い、使用中にいくつかの不満も生じています。たとえば、同時に見ることができるのは 1 つの場所だけであり、他の場所を見たい場合は、パン/チルトを調整し、カメラを前後に回転する必要があります。観察時には一定の死角と時間差が生じます。または、家の特定の場所を詳しく見たいときに、画像がぼやけていてまったく見えないなど、鮮明さが大幅に損なわれます。 Honor Select と Xiaopai Technology は共同で、「3 つのレンズとデュアル画像」を特徴とする Honor Select Xiaopai スマート カメラ プロを発売しました。業界とユーザーの問題点に対する新しいソリューションを提供します

Xiaomi Pro14の発売日 Xiaomi Pro14の発売日 Jan 05, 2024 pm 02:50 PM

Xiaomi pro14はすでに発売されており、その構成はビジネスオフィスノートとしては非常に優れており、3つのプロセッサ構成から選択でき、価格も特に高くありません。多くの友人はXiaomi Pro14の具体的な発売時期を知りません。 Xiaomi Pro14の発売時期A:Xiaomi Pro14 Ryzen Editionは2021年11月10日に予約注文可能となり、初期価格は5,299元からとなります。 Xiaomi Notebook Pro 14は2022年7月4日に発売され、7月8日午前0時に正式に発売されます。 Xiaomi pro14 の紹介 1. 画面には、解像度 2560x1600、画面対本体比最大 88%、100% sRGB 色域、およびリフレッシュ レートの 14 インチ 2.5K Super Retina スクリーンが装備されています。 120Hz。 2.外観は6シリーズを採用

Apple の A17 Pro GPU はどのような変化をもたらすのでしょうか? Apple の A17 Pro GPU はどのような変化をもたらすのでしょうか? Sep 18, 2023 pm 08:53 PM

Apple はテクノロジーの限界を押し広げ続けており、その革新性の最新の証拠は Apple A17 Pro GPU の発売です。この最先端のコンポーネントは、完全に再設計された GPU を備えており、パフォーマンス、グラフィックス、ユーザー エクスペリエンスの大幅な向上を約束します。 iPhone 15 Pro と同時に発売された Apple A17 Pro GPU は、半導体エンジニアリングの驚異です。これは 3nm プロセスを使用して構築されており、これは小型化における大きな進歩であり、これまでよりも多くのトランジスタを 1 つのチップに詰め込むことができます。この技術的功績は、電力効率とコンピューティング能力の向上につながります。 Apple A17 Pro GPU が驚異的なグラフィックスを実現 A17 Pro チップの際立った機能の 1 つは、再設計された GPU です。 Apple はグラフィックス パフォーマンスの最適化に多額の投資を行ってきました。

See all articles