【php精品源码栏目提醒】:网学会员为广大网友收集整理了,【精品】php5学习笔记(转) - 其它资料,希望对大家有所帮助!
php5 学习笔记第一节--面向对象编程面向对象编程被设计来为大型软件项目提供解决方案尤其是多人合作的项目. 当源代码增长到一万行甚至更多的时候每一个更动都可能导致不希望的副作用. 这种情况发生于模块间结成秘密联盟的时候就像第一次世界大战前的欧洲.注:喻指模块间的关联度过高相互依赖性太强.更动一个模块导致其它模块也必须跟着更动.想像一下如果有一个用来处理登录的模块允许一个信用 卡处理模块来分享它的数据库连接.当然出发点是好的节省了进行另一个数据库连接的支出.然而有时登录处理模块改变了其中一个变量的名字就可能割断了 两者间的协议.导致信用 卡模块的处 理出错进而导致处理发票的模块出错. 很快地体系中所有无关的模块都可能由此出错.因此我觉得有点戏剧性地绝大多数程序员都对耦合和封装心存感激. 耦合是两个模块间依赖程度的量度. 耦合越少越好.我们希望能够从已有的项目中抽走一个模块并在另一个新项目中使用.我们也希望在某个模块内部大规模的更动而不用担心对其他模块的影响. 封装的原则可以提供这个解决方案.模块被看待成相对独立并且模块间的数据通信通过接口来进行. 模块不通过彼此的变量名来窥探另一个模块它们通过函数来礼貌地发送请求.封装是 你可以在任何编程语言中使用的一个原则. 在
php 和许多面向过程的语言中可以偷懒是很有诱惑的.没有什么可以阻止 你通过模块来构建一个假想的 web. 面向对象编程是使程序员不会违背封装原则的一种方法.在面向对象编程中模块被组织成一个个对象. 这些对象拥有方法和属性. 从抽象的角度来看方法是一个对象的所做的动作而属性是对象的特性.从编程角度来看方法就是函数而属性是变量. 在一个理想化的面向对象体系中每个部份都是一个对象. 体系由对象及对象间通过方法来形成的联系构成.一个类定义了对象的属性. 如果你在烘烤一组甜饼对象那么类将会是甜饼机. 类的属性和方法是被调用的成员. 人们可以通过说出数据成员或者方法成员来表达.每种语言提供了不同的途径来访问对象.
php 从 c中借用概念提供一个数据类型用来在一个标识符下包含函数和变量。
最初设计
php 的时候,甚至
php3 被开发出时,
php 并不打算提供开发 超过 10 万行代码的大型项目的能力。
随着
php 和 zend 引擎的发展,开发大型项目变得有可能,但无论你的项目规模多大,用类来书写你的脚本将可以让代码 实现重用。
这是一个好主意,特别当你愿意与别人分享你的代码的时候。
有关对象的想法是计算机科学上最令人兴奋的概念之一。
开始很难掌握它,但我可以保证,一旦你掌握了它,用它的思维来思考将会非常自然。
第二节--
php5 的对象模型
php5 有一个单重继承的限制访问的可以重载的对象模型. 本章稍后会详细讨论的”继承”包含类间的父-子关系 . 另外
php 支持对属性和方法的限制性访问. 你可以声明成员为private不允许外部类访问. 最后
php 允许一个子类从它的父类中重载成员.注:
php4 中没有 private只有 public.private 对于更好地实现封装很有好处.
php5 的对象模型把对象看成与任何其它数据类型不同通过引用来传递.
php 不要求 你通过引用reference显性传递和返回对象. 在本章的最后将会详细阐述基于句柄的对象模型. 它是
php5 中最重要的新特性.有了更直接的对象模型基于句柄的体系有附加的优势: 效率提高 占用内存少并且具有更大的灵活性.在
php 的前几个版本中脚本默认复制对象.现在
php5 只移动句柄需要更少的时间. 脚本执行效率的提升是由于避免了不必要的复制. 在对象体系带来复杂性的同时也带来了执行效率上的收益. 同时减少复制意味着占用更少的内存可以留出更多内存给其它操作这也使效率提高.注:基于句柄就是说两个对象可以指向同一块内存既减少了复制动作又减少对内存的占用.zand 引擎 2 具有更大的 灵活性. 一个令人高兴的发展是允许析构--在对象销毁之前执行一个类方法. 这对于利用内存也很有好处让
php 清楚地知道什么时候没有对象的引用把空出的内存分配到其它用途.第三节--定义一个类当你声明一个类你需要列出对象应有的所有变量和所有函数—被称为属性和方法. 3.1.1 中显示了一个类的构成. 注意在大括号内你只能声明变量或者函数. 3.1.2 中显示了如何在一个类中定义三个属性和 两个方法.3.1.1class name extends another classaccess variable declarationaccess function declarationltphp//定义一个跟踪用户的类class user//属性public nameprivate password lastlogin//方法public function __constructname passwordthis-gtname namethis-gtpassword passwordthis-gtlastlogin timethis-gtaccesses// 获取最后访问的时间function getlastloginreturndatequotm d yquot this-gtlastlogin//创建一个对象的实例user new userquotleonquot quotsdf123quot//获取最后访问的时间printuser-gtgetlastlogin .quotltbrgtnquot//打印用户名printquotuser-gtnameltbrgtnquotgt当你声明属性你不需要指明数据类型. 变量可能是整型字符串或者是 另一个对象这取决于实际情况.在声明属性时增加注释是一个好主意标记上属性的含义和数据类型.当你声明一个方法你所做的和在类外部定义一个函数是一样的. 方法和属性都有各自的命名空间. 这意味着 你可以安全地建立一个与类外部函数同名的方法两者不会冲突. 例如一个类中可以定义一个名为 date的方法. 但是你不能将一个方法命名为
php 的关键字如 for或者 while.类方法可能包含
php 中所谓的 type hint. type hint 是另一个传递参数给方法的类的名字.如果你的脚本 调用方法并传递一个不是类的实例的变量
php 将产生一个”致命fatal错误” . 你可能没有给其它类型给出 type hint就像整型字符串或者布尔值. 在书写的时候type hint 是否应当包含数组类型仍存在争议.type hint 是测试函数参数或者 运算符的实例的数据类型的捷径. 你可能总是返回这个方法.确认你强制让一个参数必须是哪种数据类型如整型. 3.2.1 确保编译类只产生 widget 的实例.3.2.1
php 代码:ltphp//组件class widgetpublic namenonepublic createdfalse//装配器class assemblerpublic function makewidget wprintquotmaking w-gtnameltbrgtnquotw-gtcreatedtrue//建立一个组件对象thing new widgetthing-gtname gadget//装配组件assembler::makethinggt除了传递参数的变量外方法含有一个特殊的变量. 它代表类的个别实例. 你应当用这个来指向对象的属性和其它方法.一些面向对象的语言假设一个不合格的变量提交给本地属性但在
php 中方法的任何变量只是在方法的一定范围内. 注意在 user 类的构造函数中这个变量的使用3.1.2.
php 在属性和方法声明前定义一个访问限定语如 publicprivate 和 protected. 另外你可以用”static”来标记一个成员. 你也可以在类中声明常量. 本章稍后会有不同访问方式的相关讨论.你可以在一行中列出相同访问方式的几个属性用逗号来分隔它们. 在 3.1.2 中user 类有两个 private 属性--password 和lastlogin.第四节--构造函数和析构函数如果你在一个类中声明一个函数命名为__construct这个函数将被当成是一个 构造函数并在建立一个对象实例时被执行. 清楚地说__是两个下划线. 就像其它任何函数一样构造函数可能有参数或者默认值. 你可以定义一个类来建立一个对象并将其属性全放在一个语句statement中.你也可以定义一个名为__destruct 的函数
php 将在对象被销毁前调用这个函数. 它称为析构函数.继承是类的一个强大功能. 一个类子类/派生类可以继承另一类父类/基类的功能. 派生类将包含有基类的所有属性和方法并可以在派生类中加上其他属性和方法. 你也可以覆写基类的方法和属性. 就像 3.1.2 中显示的你可以用 extends 关键字来继承一个类.你可能想知道构造函数是如何被继承的. 当它们和其它方法一起被继承时他们不会在创建对象时被执行.如 果你需 要 这个功 能 你 需要 用第 二章 提到 的 ::运 算符 . 它 允 许你指 向一块命 名 空 间.parent 指向父类命名空间你可以用 parent::__construct 来调用父类的构造函数.一些面向对象语言在类之后命名 构造函数.
php 的前几个版本也是如此到现在这种方法仍然有效.也就是:如果你把一个类命名为 animal 并且在其中建立一个命名也是 animal 的方法则这个 方法就是构造函数.如果一个类的同时拥有__construt 构造函数和与类名相同的函数
php 将把__construct 看作构造函数.这使得用以前 的
php 版本所写的类仍然可以使用.但新的脚本
php5应当使用__construct.
php 的这种新的声明构造函数的方法可以使构造函数有一个独一无二的名称无论它所在的类的名称是什么. 这样你在改变类的名称时就不需要改变构造函数的名称.你可能在
php 中给构造函数一个像其它类方法一样的访问方式. 访问方式将会影 响从一定范围内实例化对象的能力. 这允许实现一些固定的设计模式如 singleton 模式.析构函数相反于构造函数.
php 调用它们来将一个对象从内存中销毁. 默认地
php 仅仅释放对象属性所占用的内存并销毁对象相关的资源. 析构函数允许你在使用一个对象之后执行任意代码来清除内存.当
php 决定你的脚本不再与对象相关时析构函数将被调用. 在一个函数的命名空间内这会发生在函数 return 的时候. 对于全局变量这发生于脚本结束的时候. 如果你想明确地销毁一个对象你可以给指向该对象的变量分配任何其它值. 通常将变量赋值勤为 null 或者调用unset .下面的例子中计算从类中实例化的对象的个数. counter 类从构造函数开始增值在析构函数减值.一旦你定义了一个类你可以用 new 来建立一个这个类的实例. 类的定义是设计图实例则是放在装配线上的元件. new 需要类的名称并返回该类的一个实例. 如果构造函数需要参数你应当在 new 后输入参数.
php 代码:ltphpclass counterprivate static count 0function __constructself::countfunction __destructself::count--function getcountreturn self::count//建立第一个实例c new counter//输出 1printc-gtgetcount . quotltbrgtnquot//建立第二个实例c2 new counter//输出 2printc-gtgetcount . quotltbrgtnquot//销毁实例c2 null//输出 1printc-gtgetcount . quotltbrgtnquotgt当你新建了一个实例内存会被准备来存储所有属性. 每个实例有自己独有的一组属性. 但方法是由该类的所有实例共享的.第五节--克隆
php5 中的对象模型通过引用来调用对象 但有时你可能想建立一个对象的副本并希望原来的对象的改变不影响到副本 . 为了这样的目的
php 定义了一个特殊的方法称为__clone.像__construct 和__destruct 一样前面有 两个下划线.默认地用__clone 方法将建立一个与原对象拥有相同属性和方法的对象. 如果你想在克隆时改变默认的内容你要在__clone 中覆写属性或方法.克隆的方法可以没有参数但它同时包含 this 和 that 指针that 指向被复制的对象. 如果你选择克隆自己你要小心复制任何你要你的对象包含的信息从 that 到 this. 如果你用__clone 来复制.
php 不会执行任何隐性的复制下面显示了一个用系列序数来自动化对象的例子:
php 代码:ltphpclass objecttracker //对象跟踪器private static nextserial 0private idprivate namefunction __constructname //构造函数this-gtname namethis-gtid self::nextserialfunction __clone //克隆this-gtname quotclone of that-gtnamequotthis-gtid self::nextserialfunction getid //获取 id 属性的值returnthis-gtidfunction getname //获取 name 属性的值returnthis-gtnameot new objecttrackerquotzeevs objectquotot2 ot-gt__clone//输出: 1 zeevs objectprintot-gtgetid . quot quot . ot-gtgetname . quotltbrgtquot//输出: 2 clone of zeevs objectprintot2-gtgetid . quot quot . ot2-gtgetname . quotltbrgtquotgt第六节--访问属性和方法一个对象实例的属性是变量就像
php 的其他变量一样. 但是你必须使用-gt运算符来引用它们. 不需要在属性前使用美元符. 例如 6.1 中打印 user 对象的 name 属性那一行.可以联用-gt如果一个对象的属性包含了一个对象你可以使用两个-gt运算符来得到内部对象的属性. 你甚至可以用双重引用的字符串来放置这些表达式. 看 6.5 中的例子对象 house中的属性 room 包含了一组 room 对象.访问方法和访问属性类似. -gt运算符用来指向实例的方法. 在例子 6.1 中调用 getlastlogin就是. 方法执行起来和类外的函数几乎相同.如果一个类从另一类中继承而来父类中的属性和方法将在子类中都有效即使在子类中没有声明. 像以前提到过的继承是非常强大的. 如果你想访问一个继承的属性你只需要像访问基类自己的属性那样引用即可使用::运算符.
php 代码:ltphpclass roompublic namefunction __constructnamequotunnamedquotthis-gtname nameclass house//array of roomspublic room//create empty househome new house//add some roomshome-gtroom new roomquotbedroomquothome-gtroom new roomquotkitchenquothome-gtroom new roomquotbathroomquot//show the first room of the houseprinthome-gtroom0-gtnamegtphp 有两个特殊的命名空间 arent 命名空间指向父类self 命名空间指向当前的类. 例子 6.6中显示了如何用 parent 命名空间来调用父类中的构造函数. 同时也用 self 来在构造函数中调用另一个类方法.ltphpclass animal //动物public blood //热血 or 冷血属性public namepublic function __constructblood namenullthis-gtblood bloodifnamethis-gtname nameclass mammal extends animal //哺乳动物public furcolor //皮毛颜色public legsfunction __constructfurcolor legs namenullparent::__constructquotwarmquot namethis-gtfurcolor furcolorthis-gtlegs legsclass dog extends mammalfunction __constructfurcolor nameparent::__constructfurcolor 4 nameself::barkfunction barkprintquotthis-gtname says woofquotd new dogquotblack and tanquot quotangusquotgt第四章中介绍了如何调用函数. 对于对象的成员来是这样调用的:如果你需要在运行时确定变 量 的 名 称 你 可 以 用 this-gtproperty 这 样 的 表达 式 . 如 果你 想 调 用 方 法 可 以 用obj-gtmethod.你也可以用-gt运算符来返回一个函数的值这在
php 以前的版本中是不允许的. 例如你可以写一个像这样的表达式: obj-gtgetobject-gtcallmethod. 这样避免了使用一个中间变量也有助于实现某些设计模式如 factory 模式.第七节--类的静态成员类的静态成员与一般的类成员不同: 静态成员与对象的实例无关只与类本身有关. 他们用来实现类要封装的功能和数据但不包括特定对象的功能和数据. 静态成员包括静态方法和静态属性.静态属性包含在类中要封装的数据可以由所有类的实例共享. 实际上除了属于一个固定的类并限制访问方式外类的静态属性非常类似于函数的全局变量我们在下例中使用了一个静态属性 counter::count. 它属于 counter 类而不属于任何 .counter 的实例.你不能用 this 来引用它但可以用 self 或其它有效的命名表 达 在例子中getcount 方法返回 self::count而不是 counter::count.静态方法则实现类需要封装的功能与特定的对象无关. 静态方法非常类似于全局函数. 静态方法可以完全访问类的属性也可以由对象的实例来访问不论访问的限定语是否是什么.在 6.3 例中getcount 是一个普通的方法用-gt来调用.
php 建立一个 this 变量尽管方法没有使用到.但是getcount 不属于任何对象.在有些情况下我们甚至希望在不存在有效的对象时调用它那么 就应该使用静态方法.
php 将不在静态方法内部建立 this 变量即使你从一个对象中调用它们.例子 6.7 由 6.3 改变 getcount 为静态方法而来. static 关键字不能阻止一个实例用-gt运算符来调用 getcount但
php 将不在方法内部建立 this 变量.如果你使用 this-gt来调用将会出错.//6.3 例指第四节--构造函数和析构函数中的例子参看前文通过两个例子的比较你可以很好掌握//static 方法与普通方法之间的区别.你可以写一个方法通过判断 this 是否建立来显示是否它被静态地或者非静态地调用. 当然如果你用了 static 关键字不管它怎样被调用这个方法总是静态的.你的类也可以定义常量属性不需要使用 public static只需要用 const 关键字即可. 常量属性总是静态的.它们是类的属性而不是实例化该类的对象的属性.listing 6.7 static membersphp 代码:ltphpclass counterprivate static count 0const version 2.0function __constructself::countfunction __destructself::count--static function getcountreturn self::count//创建一个实例则__construct将执行c new counter//输出 1printcounter::getcount . quotltbrgtnquot//输出类的版本属性printquotversion used: quot . counter::version . quotltbrgtnquotgt第八节--访问方式
php5 的访问方式允许限制对类成员的访问. 这是在
php5 中新增的功能但在许多面向对象语言中都早已存在. 有了访问方式才能开发一个可靠的面向对象应用程序并且构建可重用的面向对象类库.像 c和 java 一样
php 有三种访问方式 ublicprivate 和 protected. 对于一个类成员的访问方式可以是其中之一. 如果你没有指明访问方式默认地访问方式为 public. 你也可以为静态成员指明一种访问方式将访问方式放在 static 关键字之前如 public static.public 成员可以被毫无限制地访问.类外部的任何代码都可以读写 public 属性. 你可以从脚本的任何地方调用一个 public 方法. 在
php 的前几个版本中所有方法和属性都是 public这让人觉得对象就像是结构精巧的数组.private私有成员只在类的内部可见. 你不能在一个 private 属性所在的类方法之外改变或读取它的值. 同样地只有在同一个类中的方法可以调用一个 private 方法. 继承的子类也不能访问父类中的 private 成员.要注意类中的任何成员和类的实例都可以访问 private 成员. 看例子 6.8equals 方法将 两个 widget 进行比较.运算符比较同一个类的两个对象但这个例子中每个对象实例都有唯一的 id.equals 方法只比较 name 和 price. 注意 equals 方法如何访问另一个 widget 实例的private 属性. java 和 c 都允许这样的操作.listing 6.8 private membersphp 代码:ltphpclass widgetprivate nameprivate priceprivate idpublic function __constructname pricethis-gtname namethis-gtprice floatvalpricethis-gtid uniqid//checks if two widgets are the same 检查两个 widget 是否相同public function equalswidgetreturnthis-gtname widget-gtnameandthis-gtprice widget-gtpricew1 new widgetcog 5.00w2 new widgetcog 5.00w3 new widgetgear 7.00//trueifw1-gtequalsw2printquotw1 and w2 are the sameltbrgtnquot//falseifw1-gtequalsw3printquotw1 and w3 are the sameltbrgtnquot//false includes id in comparisonifw1 w2 //不等因为 id 不同printquotw1 and w2 are the sameltbrgtnquotgt如果你对面向对象编程不熟悉你可能想知道用 private 成员的目的是什么. 你可以回忆一下封装和 耦合.
上一篇:
【精品】程序员面试之葵花宝典2
下一篇:
病理学实验课多样化教学方法探讨