찾다
PHP4之真OOJun 21, 2016 am 09:14 AM
displayfunctionthis

本文的作者Johan Persson是PHP中著名的JpGraph图表类库的开发者. 本文是作者对于在PHP4中进行面向对象开发时需要注意的几个小问题的总结.
翻译: Binzy Wu [Mail: Binzy at JustDN dot COM], 水平有限, 欢迎探讨. 2004-2-4

简介
本文的对象是那些曾使用更加成熟的OO [1] 语言, 如Eiffel, Java, C# [2] or C++(), 进行开发的朋友(如我自己). 在使用PHP4进行完全的OO开发时有着许多的语义[3] (semantic)
上的陷阱[4].

希本文内容可助人避我曾犯之错.

引用 VS 拷贝语义
这基本上是错误的主要来源(至少对于我来说).即使在PHP的文档中你可以读到PHP4较之引用更多使用拷贝语义(如其他我所知的面向对象语言), 但这仍将使你最后在一些细小之处困扰.

接下来的两部分用于阐述二个小的例子, 在这二个例子中拷贝语义也许会令你惊讶.

要时刻牢记重要的是一个类的变量不是一个指向类的指针而是实际的类自己本身[5]. 大多数问题引发自对于赋值操作符(=)的误解, 即以为是给一个对象一个别名, 而实际上却是一个新的拷贝. 例如假设$myObj是某个类的实例, 并且它有一个Set()方法. 那么下面的代码也许不会像一个C++(或者Java)程序员所期望的那样工作.

function SomeFunction($aObj) { $aObj->Set(10); }

SomeFunction ($myObj);



那么现在, 很容易便会认为该函数所调用的Set()方法会作用于$myObj. 但这是错的!

其实发生的是$myObj被拷贝为一个新的, 与原对象一样的拷贝----参数$aObj. 然后当Set()方法被调用时, 它仅仅作用于本地拷贝而非原参数----$myObj.

在包含直接或间接(如上)赋值操作的地方就会发生各种各样的上述问题.

为了函数能像你所期望的那样行动(也许是), 那么你不得不通过修改方法申明来告诉PHP使用引用来传递对象, 如:
Function SomeFunction(&$aObj)


如果你再一次尝试上面的代码, 那么你会发现Set()方法将作用于原来的参数上, 因为现在我们在作用中创建了一个$myObj的别名----$aObj.

但是你不得不小心, 因为即使是&操作符也不是在任何时候都能救你, 如下面的举例.

从一个引用来获得引用

假设有如下代码:
$myObject = new SomeClass();$myRefToObject = &$myObject;


如果我们现在想要一个引用的拷贝(因某些理由), 那么我们要做什么呢? 你可能会由于$myRefToObject已经是引用而试图那么写:
$myCopyRefToObject = $myRefToObject;

正确么? 不! PHP会创建$myRefToObject所引用对象的新拷贝. 如果你想拷贝一个对象的引用, 你不得不这么写:
$myCopyRefToObject = &$myRefToObject;


在与前所述例子相当的C++的例子中, 便会创建一个引用的引用. 与其在PHP中不同. 这是一个经验丰富的C++程序员常会作的直觉假设相反的, 而这会是你的PHP程序中小BUG的来源.

请小心由此所产生的间接(传递参数)或直接的问题.

我个人所达成的结论, 即最好的避免这些语义陷阱的方法是总是用引用来传递对象或者对象赋值. 这不仅仅改进了运行速度(更少的数据拷贝), 而且可以对像我这样的老狗而言使语义更加可预测.

在构造函数中对$this使用引用

在一个对象的构造函数里初始化作为其他对象发现者(Observer[6])的对象是一个常见的模式. 下面几行代码便是一个示例:
class Bettery
{
function Bettery() {…};
function AddObserver($method, &$obj)
{
$this->obs[] = array($obj, &$method)
}
function Notify(){…}
}
class Display
{
function Display(&$batt)
{
$batt->AddObserver("BatteryNotify",$this);
}
function BatteryNotify() {…}
}


但是, 这并不会正常工作, 如果你是这么实例化对象的:
$myBattery = new Battery();$myDisplay = new Display($myBattery);


这么做的错误在于new时在构造函数中使用$this并不会返回同一个对象. 反而会返回最近创建对象的一个拷贝. 即在调用AddObserver()时所传送的对象于原对象不是同一个. 然后当Battery类尝试通知所有它的观察者(Observer)(通过调用他们的Notify方法)时, 它并不会调用我们所创建的Display类而是$this所代表的类(即我们所创建的Display类的拷贝). 因此如果Notify()方法更新了一些实例变量, 并不像我们所设想原Display类会被更新, 因为更新的其实是个拷贝. 为了让它工作, 你必须使构造函数返回同一个对象, 正如与最初$this所象征的那样. 可以通过添加&符号于Display的构造, 如$myDisplay = & new Display($myBattery);
一个直接的结果是任何Display类的Client必须了解Display的实现细节. 事实上, 这会产生一个可能引起争论的问题: 所有对象的构建必须使用额外的&符号. 就我所说的基本上是安全的, 但忽略它可能会在某些时候得到不想要的如上述示例般的作用.

在JpGraph中使用了另一种方法来解决. 即需要使用通过添加一个能安全的使用&$this引用的”Init()”方法的所谓二阶段构造来”new”一个对象(仅仅是因为在构造函数中的$this引用返回对象的一个拷贝而不如所期望的那样执行). 因此上面的例子会如下实现:
$myBattery = new Battery();
$myDisplay = new Display();
$myDisplay->Init($myBattery);


如JPGraph.php中的”LinearScale”类.


使用foreach

另外一个相似代码却不同结果的问题是”foreach”结构的问题. 研究一下下面的二个循环结构的不同版本.
// Version 1
foreach( $this->plots as $p )
{
$p->Update();
}



// Version 2
for( $i=0; $iplots); ++$i )
{
$this->plots[$i]->Update();
}


现在是一个价值10美元的问题[7]: version1==version2么?

令人惊讶的答案是:No! 这是细小却是关键的不同. 在Version 1中, Update()方法将作用于”plots[]”数组中对象的副本. 因此数组中原来的对象并不会被更新.

在Version 2中Update()方法将如预期的作用于”plots[]”数组中的对象.

正如第一部分所陈述的, 这是PHP将对象实例作为对象本身来处理而非作为对象引用的结果.

译注:
[1]. OO: Object-Oriented, 面向对象.
[2]. 原文并无C#, 全因Binzy的个人爱好.
[3]. Semantic在本文中被译为”语义”, 如有任何建议请和Binzy联系.
[4]. C++中有一本著名的”C++ Gotchas”.
[5]. 这里的类应该是指Instance, 即实例.
[6]. 可参见”[GoF95]”, 即”Design Patterns”.
[7]. 有个挺有趣的关于交易的小故事:
有人用60美元买了一匹马, 又以70美元的价钱卖了出去;然后, 他又用80美元把它买回来, 最后以90美元的价钱卖出.在这桩马的交易中, 他? (A)赔了10美元; (B)收支平衡; ©赚了10美元;(D)赚了20美元; (E)赚了30美元.
这是美国密执安大学心理学家梅尔和伯克要大学生们计算的一个简单的算术题.结果只有不到40%的大学生能够作出正确答案, 多数人认为只赚了10美元.其实, 问题的条件十分明确, 这是两次交易, 每次都赚10美元, 而很多人却错误地认为当他用80美元买回来时己经亏损了10美元. 有趣的是, 同一问题, 以另一种方式提出来:有一个人用60美元买了一匹白马, 又以70元的值卖出去;然后, 用80美元买了一匹黑马, 又以90美元的值卖出去.在这桩买卖马的交易中, 他____(把同样的五个选择罗列出来).这时, 另一组大学生在回答上述问题时, 结果大家都答对了.



성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
比较:Apple Studio Display vs Samsung Smart Monitor M8比较:Apple Studio Display vs Samsung Smart Monitor M8May 11, 2023 pm 10:46 PM

三星智能显示器M8与AppleStudio显示器:设计和尺寸自推出以来,AppleStudioDisplay就被比作iMac,由相对简单的L形支架上的相对薄的面板组成。这是一种众所周知且深受喜爱的美学,三星似乎借用了它的展示。三星SmartMonitorM8采用了与外观非常相似的支架上的薄屏幕的相同想法。一些次要元素有所不同,例如左下角的小部分有点突出,三星的下巴很薄,但它们在基本设计方面似乎很接近。三星似乎从24英寸iMac中获得了很多灵感。苹果的显示器比三星的要小

Apple Studio Display 的电源线是可拆卸的,但需要特殊工具Apple Studio Display 的电源线是可拆卸的,但需要特殊工具May 17, 2023 pm 03:05 PM

AppleStudioDisplay现已在商店正式发售,全球已有多家客户购买了该产品。与ProDisplayXDR不同,StudioDisplay有一个独特的电源连接器,似乎是不可拆卸的。事实证明,电缆是可拆卸的,但您需要使用特殊工具才能将其卸下。苹果在其网站上表示,StudioDisplay的电源线是不可拆卸的——而且很多用户都这么认为。那是因为用你的双手移除电缆似乎是不可能的,但幸运的是,电缆可以从显示器上分离。,Apple有一个特殊的工具,用于从其新的StudioDispl

对比:Apple Studio Display vs LG UltraFine 5K Display 哪个好?对比:Apple Studio Display vs LG UltraFine 5K Display 哪个好?Apr 16, 2023 pm 08:25 PM

StudioDisplay和LGUltraFine5KDisplay在市场上占有相似的位置,但苹果的显示器要贵300美元。以下是您需要了解的有关这些显示器如何比较的所有信息。六年在科技领域是一段很长的时间,而这也是苹果出售一款价格不超过5,000美元的品牌显示器以来的时间。在此期间,Apple与LG合作销售专门迎合Mac用户的LGUltraFine系列。2019年,Apple停止销售这些LG显示器,转而支持ProDisplayXDR,这在价格适中的Mac友好显

display是什么意思display是什么意思Oct 26, 2023 am 11:50 AM

display通常指的是将数据、信息或结果以某种方式展示给用户或输出到屏幕或其他设备上的操作或功能。具体含义:1、在命令行界面(CLI)中,display可能指的是将文本、表格或其他格式的数据输出到终端窗口,供用户查看或分析;2、在图形用户界面(GUI)中,display可能指的是将图像、文本、图表等内容显示在应用程序的窗口或界面上,以供用户交互或浏览等等。

Boot Camp 更新以支持 Apple Studio DisplayBoot Camp 更新以支持 Apple Studio DisplayMay 20, 2023 pm 11:34 PM

在Mac上运行Windows的IntelMac用户现在可以更新BootCamp中的驱动程序,以支持Apple的StudioDisplay。Apple会定期更新BootCamp,以引入对新硬件的支持,以及典型的兼容性和性能改进。在3月份的软件更新中,Apple已启用BootCamp以与新的StudioDisplay配合使用。将BootCamp带到6.1.17版的更新引入了两个关键支持元素。首先,它增加了对StudioDisplay的兼容性,确

display有哪些取值display有哪些取值Nov 20, 2023 pm 05:28 PM

display的取值有block、inline、none、inline-block、flex、grid、table、inline-table和list-item等。详细介绍:1、block,将元素渲染为块级元素,块级元素在页面上形成一个块,并且独占一行;2、inline,将元素渲染为内联元素。内联元素不会独占一行,可以与其他元素并排;3、none,此值指定元素不会在页面上等等。

Apple Studio Display 适用于 Windows,但有一些限制Apple Studio Display 适用于 Windows,但有一些限制Apr 14, 2023 pm 03:49 PM

Apple本周发布了StudioDisplay,它采用27英寸5K面板,结合了摄像头、麦克风和扬声器,当用户将显示器连接到Mac时,它们可以协同工作。窗户呢?如果出于某种原因您需要在WindowsPC上使用Apple的1599美元显示器,您可以,但有一些限制。当通过Thunderbolt连接(并非每台PC都支持)插入WindowsPC时,StudioDisplay被识别为常规显示器。也就是说,如果您购买了其中一个以将其与Windows一起使用,则需要记

Google Pixel 8 display problems: Repair program enables 3 years of free serviceGoogle Pixel 8 display problems: Repair program enables 3 years of free serviceJun 15, 2024 pm 06:50 PM

SincethelaunchoftheGooglePixel8(approx.513eurosatAmazon,limited-timedeal),therehavebeenanincreasingnumberofreportsfromuserscomplainingaboutaverticallineonthedisplay.Thiscanmanifestitselfindifferentways-thecolorand

See all articles

핫 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 Hentai를 무료로 생성하십시오.

뜨거운 도구

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기