给猪的鼻子插一根葱_PHP
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 */

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











많은 사용자는 Xiaomi Mi Pad 6 또는 Mi Pad 6 중 어느 것을 구입할 가치가 있는지 확신하지 못합니다. 구성 관점에서 볼 때 Pro의 더 높은 구성을 권장하지만 가격과 자체 예산에 따라 다릅니다. 다른 제품 포지셔닝 그룹도 다릅니다. Xiaomi Mi Pad 6 또는 Pro 중 어느 것을 구입할 가치가 있습니까? 답변: 성능과 카메라 배터리 수명 측면에서 Xiaomi Mi Pad 6 Pro가 더 좋습니다. 1. 프로세서 샤오미 패드 6: 스냅드래곤 870 샤오미 미 패드 6 프로: 더욱 강력해진 1세대 스냅드래곤 8+ 프로세서 2. 배터리 크기 샤오미 미 패드 6: 8840mAh, 67W 2차 충전 샤오미 미 패드 6 프로: 8600mAh, 33W Xiaomi Mi Pad 6을 충전하면 배터리 수명이 더 길어지지만 충전 속도가 느려집니다. 3. Xiaomi Mi Pad 6로 사진 찍기

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니트 크기 6.29x3 .02x0.32인치 6.33x3.06x0.31인치 무게 221g 240g

많은 사용자는 Xiaomi Mi Band 8을 처음 접했을 때 켜는 방법을 모릅니다. 실제로 방법은 매우 간단합니다. USB 데이터 케이블을 찾아 시계를 전원 공급 장치에 연결하기만 하면 됩니다. , 잠시 동안 충전 한 다음 버튼을 눌러 켤 수 있습니다. Xiaomi Mi Band 8pro 켜는 방법 1. 먼저 시계를 설치합니다. 즉, 테마와 스트랩을 양쪽에 연결합니다. 2. 그런 다음 처음으로 시계를 켤 때 충전 케이블을 연결해야 합니다. 연결 방법은 시계 하단에 있습니다. 3. 시계가 진동하여 전원이 켜질 때까지 기다린 다음 휴대폰에 연결합니다. >>>

JSON(JavaScriptObjectNotation)은 웹 애플리케이션 간의 데이터 교환을 위한 일반적인 형식이 된 경량 데이터 교환 형식입니다. PHP의 json_encode() 함수는 배열이나 객체를 JSON 문자열로 변환할 수 있습니다. 이 기사에서는 구문, 매개변수, 반환 값 및 구체적인 예를 포함하여 PHP의 json_encode() 함수를 사용하는 방법을 소개합니다. 구문 json_encode() 함수의 구문은 다음과 같습니다. st

MacBook Air는 Apple 노트북입니다. 많은 사용자가 MacBook Air와 Pro의 차이점을 궁금해합니다. 이 두 노트북은 프로세서 코어, 주요 주파수 및 그래픽 카드 유형에 약간의 차이가 있습니다. MacBook Air와 Pro의 차이점: 1. 다양한 프로세서 코어 및 스레드: MacBook Air의 프로세서에는 듀얼 코어와 4개의 스레드가 있습니다. Pro는 4개의 코어와 8개의 스레드로 MacBook Air보다 강력합니다. 2. 프로세서의 기본 주파수는 다릅니다. MacBook Air 프로세서의 기본 주파수는 1.6GHz입니다. Pro 프로세서의 주요 주파수는 1.4GHz로 Macbook Air보다 약간 낮습니다. 3. 다양한 그래픽 카드: macbookair 채택

Apple은 계속해서 기술의 경계를 확장하고 있으며, 혁신의 최신 증거는 Apple A17 Pro GPU의 출시입니다. 이 최첨단 구성 요소는 완전히 재설계된 GPU를 갖추고 있어 성능, 그래픽 및 사용자 경험이 크게 향상됩니다. iPhone 15 Pro와 함께 출시된 Apple A17 Pro GPU는 반도체 엔지니어링의 경이로움입니다. 이 제품은 소형화의 큰 도약을 의미하는 3nm 공정을 사용하여 제작되었으며, 이전보다 더 많은 트랜지스터를 단일 칩에 담았습니다. 이러한 기술적 위업은 더 큰 전력 효율성과 컴퓨팅 성능으로 이어집니다. Apple A17 Pro GPU는 놀라운 그래픽을 제공합니다. A17 Pro 칩의 뛰어난 기능 중 하나는 재설계된 GPU입니다. Apple은 그래픽 성능 최적화에 막대한 투자를 해왔습니다.

샤오미 pro14는 이미 시중에 나와 있는데, 그 구성은 비즈니스 오피스 노트북으로 아주 좋습니다. 선택할 수 있는 프로세서 구성이 3가지가 있고, 가격도 특별히 높지 않습니다. 많은 친구들이 Xiaomi Pro14의 구체적인 출시 시간을 모릅니다. Xiaomi Pro14 출시 시간 A: Xiaomi Pro14 Ryzen Edition은 2021년 11월 10일에 사전 주문이 가능하며 초기 가격은 5,299위안부터 시작됩니다. 샤오미 노트북 프로 14는 2022년 7월 4일 출시되며, 7월 8일 자정에 정식 판매될 예정입니다. Xiaomi pro14 소개 1. 화면에는 2560x1600의 해상도, 최대 88%의 화면 대 본체 비율, 100% sRGB 색역 및 재생률을 갖춘 14인치 2.5K Super Retina 화면이 장착되어 있습니다. 120Hz. 2. 외관은 6 시리즈를 채택

집에 카메라를 설치하셨나요? 최근 몇 년간 가정용 카메라 제품이 갑자기 인기를 끌었습니다. 주변 친구들에게 물어보니 집집마다 하나씩 있고, 한 개 이상 있는 집도 있다고 하더군요. 하지만 제품이 인기를 끌면서 사용 중 불만이 제기되기도 했습니다. 예를 들어 동시에 한 곳만 볼 수 있고, 다른 곳을 보려면 팬/틸트를 조정하고 카메라를 앞뒤로 회전시켜야 볼 수 있는 사각지대와 시간차가 있습니다. 또는 집의 특정 위치를 자세히 살펴보고 싶을 때 사진이 흐릿하고 전혀 볼 수 없는 경우 등... 경험이 크게 저하됩니다. Honor Select와 Xiaopai Technology는 "3개의 렌즈와 듀얼 이미지"를 갖춘 Honor Select Xiaopai Smart Camera Pro를 공동 출시했습니다. 업계 및 사용자의 문제점에 대한 새로운 솔루션 제공
