php.net

对象

在类定义内部,可以用 new self 和 new parent 创建新对象。

当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。可以用克隆给一个已创建的对象建立一个新实例。

  1. <?php
  2. $instance = new SimpleClass();
  3. $assigned = $instance;
  4. $reference =& $instance;
  5. $instance->var = '$assigned will have this value';
  6. $instance = null; // $instance and $reference become null
  7. var_dump($instance);
  8. var_dump($reference);
  9. var_dump($assigned);
  10. ?>

输出:

  1. NULL
  2. NULL
  3. object(SimpleClass)#1 (1) {
  4. ["var"]=>
  5. string(30) "$assigned will have this value"
  6. }

PHP 5.3.0 引进了两个新方法来创建一个对象的实例:

  1. <?php
  2. class Test
  3. {
  4. static public function getNew()
  5. {
  6. return new static;
  7. }
  8. }
  9. $obj1 = new Test();
  10. $obj2 = new $obj1; //第一种
  11. $obj3 = Test::getNew();

自 PHP 5.5 起,使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。

类常量

可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号

  1. <?php
  2. class MyClass
  3. {
  4. const constant = 'constant value';
  5. function showConstant() {
  6. echo self::constant . "\n";
  7. }
  8. }

静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)

抽象类

任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。

  1. <?php
  2. abstract class AbstractClass
  3. {
  4. // 强制要求子类定义这些方法
  5. abstract protected function getValue();
  6. abstract protected function prefixValue($prefix);
  7. // 普通方法(非抽象方法)
  8. public function printOut() {
  9. print $this->getValue() . "\n";
  10. }
  11. }

Trait

传统继承增加了水平特性的组合,避免传统多继承和 Mixin 类相关典型问题。优先级:当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。

  1. <?php
  2. trait ezcReflectionReturnInfo {
  3. function getReturnType() { /*1*/ }
  4. function getReturnDescription() { /*2*/ }
  5. }
  6. class ezcReflectionMethod extends ReflectionMethod {
  7. use ezcReflectionReturnInfo;
  8. /* ... */
  9. }
  10. class ezcReflectionFunction extends ReflectionFunction {
  11. use ezcReflectionReturnInfo;
  12. /* ... */
  13. }

多个 trait

通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

  1. <?php
  2. trait Hello {
  3. public function sayHello() {
  4. echo 'Hello ';
  5. }
  6. }
  7. trait World {
  8. public function sayWorld() {
  9. echo 'World';
  10. }
  11. }
  12. class MyHelloWorld {
  13. use Hello, World;
  14. public function sayExclamationMark() {
  15. echo '!';
  16. }
  17. }
  18. $o = new MyHelloWorld();
  19. $o->sayHello();
  20. $o->sayWorld();

解决trait冲突

如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。

需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。as 操作符可以将其中一个冲突的方法以另一个名称来引入。

示例:定义了使用 trait B 中的 smallTalk 以及 trait A 中的 bigTalk,用了 as 操作符来定义了 talk 来作为 B 的 bigTalk 的别名。

  1. <?php
  2. trait A {
  3. public function smallTalk() {
  4. echo 'a';
  5. }
  6. public function bigTalk() {
  7. echo 'A';
  8. }
  9. }
  10. trait B {
  11. public function smallTalk() {
  12. echo 'b';
  13. }
  14. public function bigTalk() {
  15. echo 'B';
  16. }
  17. }
  18. class Aliased_Talker {
  19. use A, B {
  20. B::smallTalk insteadof A;
  21. A::bigTalk insteadof B;
  22. B::bigTalk as talk;
  23. }
  24. }

修改访问控制权限

使用as

  1. <?php
  2. trait HelloWorld {
  3. public function sayHello() {
  4. echo 'Hello World!';
  5. }
  6. }
  7. // 修改 sayHello 的访问控制
  8. class MyClass1 {
  9. use HelloWorld { sayHello as protected; }
  10. }
  11. // 给方法一个改变了访问控制的别名
  12. // 原版 sayHello 的访问控制则没有发生变化
  13. class MyClass2 {
  14. use HelloWorld { sayHello as private myPrivateHello; }
  15. }
  16. ?>

其他

其它 trait 也能够使用 trait。

trait 支持抽象方法的使用。

Trait 同样可以定义属性。

匿名类

匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来:

  1. <?php
  2. class Outer
  3. {
  4. private $prop = 1;
  5. protected $prop2 = 2;
  6. protected function func1()
  7. {
  8. return 3;
  9. }
  10. public function func2()
  11. {
  12. return new class($this->prop) extends Outer {
  13. private $prop3;
  14. public function __construct($prop)
  15. {
  16. $this->prop3 = $prop;
  17. }
  18. public function func3()
  19. {
  20. return $this->prop2 + $this->prop3 + $this->func1();
  21. }
  22. };
  23. }
  24. }
  25. echo (new Outer)->func2()->func3();

魔术方法

不可访问属性、不可访问方法:未定义或不可见的类属性或方法

在给不可访问属性赋值时,__set() 会被调用。

读取不可访问属性的值时,__get() 会被调用。

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

当对不可访问属性调用 unset() 时,__unset() 会被调用。

在对象中调用一个不可访问方法时,__call() 会被调用。

在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。

serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。

unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

  1. public void __set ( string $name , mixed $value )
  2. public mixed __get ( string $name )
  3. public bool __isset ( string $name )
  4. public void __unset ( string $name )
  5. public mixed __call ( string $name , array $arguments )
  6. public static mixed __callStatic ( string $name , array $arguments )
  7. __construct(), __destruct(), __sleep(), __wakeup(), __toString(), __invoke(),__set_state(), __clone() __debugInfo()

示例:

  1. <?php
  2. class PropertyTest {
  3. /** 被重载的数据保存在此 */
  4. private $data = array();
  5. /** 重载不能被用在已经定义的属性 */
  6. public $declared = 1;
  7. /** 只有从类外部访问这个属性时,重载才会发生 */
  8. private $hidden = 2;
  9. public function __set($name, $value)
  10. {
  11. echo "Setting '$name' to '$value'\n";
  12. $this->data[$name] = $value;
  13. }
  14. public function __get($name)
  15. {
  16. echo "Getting '$name'\n";
  17. if (array_key_exists($name, $this->data)) {
  18. return $this->data[$name];
  19. }
  20. $trace = debug_backtrace();
  21. trigger_error(
  22. 'Undefined property via __get(): ' . $name .
  23. ' in ' . $trace[0]['file'] .
  24. ' on line ' . $trace[0]['line'],
  25. E_USER_NOTICE);
  26. return null;
  27. }
  28. /** PHP 5.1.0之后版本 */
  29. public function __isset($name)
  30. {
  31. echo "Is '$name' set?\n";
  32. return isset($this->data[$name]);
  33. }
  34. /** PHP 5.1.0之后版本 */
  35. public function __unset($name)
  36. {
  37. echo "Unsetting '$name'\n";
  38. unset($this->data[$name]);
  39. }
  40. /** 非魔术方法 */
  41. public function getHidden()
  42. {
  43. return $this->hidden;
  44. }
  45. }

call示例:arguments是一个数组

  1. <?php
  2. class MethodTest
  3. {
  4. public function __call($name, $arguments)
  5. {
  6. // 注意: $name 的值区分大小写
  7. var_dump($arguments);
  8. }
  9. /** PHP 5.3.0之后版本 */
  10. public static function __callStatic($name, $arguments)
  11. {
  12. // 注意: $name 的值区分大小写
  13. var_dump($arguments);
  14. }
  15. }
  16. $obj = new MethodTest;
  17. $obj->runTest('in object context','fyfy');
  18. MethodTest::runTest('in static context'); // PHP 5.3.0之后版本
  19. ?>
  20. //输出类似
  21. /*
  22. array(2) {
  23. [0] =>
  24. string(17) "in object context"
  25. [1] =>
  26. string(4) "fyfy"
  27. }
  28. array(1) {
  29. [0] =>
  30. string(17) "in static context"
  31. }
  32. */

遍历对象

默认情况下,所有可见属性都将被用于遍历。

  1. <?php
  2. class MyClass
  3. {
  4. public $var1 = 'value 1';
  5. public $var2 = 'value 2';
  6. public $var3 = 'value 3';
  7. protected $protected = 'protected var';
  8. private $private = 'private var';
  9. function iterateVisible() {
  10. echo "MyClass::iterateVisible:\n";
  11. foreach($this as $key => $value) {
  12. print "$key => $value\n";
  13. }
  14. }
  15. }
  16. $class = new MyClass();
  17. foreach($class as $key => $value) {
  18. print "$key => $value\n";
  19. }
  20. echo "\n";
  21. $class->iterateVisible();
  22. ?>

对象复制

clone 关键字,浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。

示例:关于浅复制

  1. <?php
  2. class subclass{
  3. public $var1='subclass default';
  4. }
  5. class MyClass
  6. {
  7. public $var1 = 'myclass default';
  8. public $object;
  9. function __construct(){
  10. $this->object=new subclass();
  11. }
  12. }
  13. $object1 = new MyClass();
  14. $object2 = clone $object1;
  15. $object1->object->var1='object1 change';
  16. $object1->var1='object1 change';
  17. print_r($object1);
  18. print_r($object2);
  19. ?>

输出结果:

  1. MyClass Object
  2. (
  3. [var1] => object1 change
  4. [object] => subclass Object
  5. (
  6. [var1] => object1 change
  7. )
  8. )
  9. MyClass Object
  10. (
  11. [var1] => myclass default
  12. [object] => subclass Object
  13. (
  14. [var1] => object1 change
  15. )

对象比较

==:两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。

===:必须是同一个对象。

那些教程没有的php2-对象的更多相关文章

  1. 【PHP面向对象(OOP)编程入门教程】22.把对象串行化serialize()方法,__sleep()方法,__wakeup()方法

    有时候需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串,等到达另一端时,再还原为原来的对象,这个过程称之为串行化(也叫序列化), 就像我们现在想把一辆汽车通过轮船运到美国去,因为 ...

  2. Fastify 系列教程四 (求对象、响应对象和插件)

    Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...

  3. unity3d的playmaker插件使用教程,三、对象出入触发,声音播放

    对象出入触发是游戏常见的情形.包含同一时候声音播放 首先建立进去区域.新建一个立方体,去掉mesh render. 而且选中 is trigger同意进入 样例里用了unity3d的第一人视角控制,可 ...

  4. BIND简易教程(0):在Ubuntu下源码安装BIND(其实跟前面的教程没太大关系)

    之前介绍过BIND的基本使用啦.关于BIND的入门级使用方法见:http://www.cnblogs.com/anpengapple/p/5877661.html简易教程系列,本篇只讲BIND安装. ...

  5. 【PHP面向对象(OOP)编程入门教程】17.克隆对象__clone()方法

    有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象, ...

  6. 廖雪峰js教程笔记10 浏览器对象

    JavaScript可以获取浏览器提供的很多对象,并进行操作. window window对象不但充当全局作用域,而且表示浏览器窗口. window对象有innerWidth和innerHeight属 ...

  7. 廖雪峰js教程笔记8 date对象介绍和处理

    在JavaScript中,Date对象用来表示日期和时间. 要获取系统当前时间,用: var now = new Date(); now; // Wed Jun 24 2015 19:49:22 GM ...

  8. 那些教程没有的php3-命名空间

    php.net (PHP 5 >= 5.3.0, PHP 7) 定义命名空间 虽然任意合法的PHP代码都可以包含在命名空间中,但只有以下类型的代码受命名空间的影响,它们是:类(包括抽象类和tra ...

  9. 那些教程没有的php1-基础知识补漏

    php.net 字符串 heredoc结构 类似双引号,其中的变量会被解析.严格遵循下边的格式,结束标识符这行除了可能有一个分号(;)外,绝对不能包含其它字符. <?php $str = < ...

随机推荐

  1. win10上安装Docker

    方法1:具体我没有试过,不知道win10下可以么.http://blog.csdn.net/zistxym/article/details/42918339 方法2: 先安装VirtualBox(下载 ...

  2. lxde桌面默认快捷键

    ctrl+alt+左右      选择左右桌面shift+alt+左右     当前窗口送至左右桌面房子键+F1~F4       切换桌面1-4房子键+d           显示桌面alt+esc ...

  3. Visual Studio 2013开启JavaScript的智能提示功能

    在前一次的发布的时候,我们共享了Visual Studio 2013中Windows Azure移动服务的集成和功能.其中包含了移动服务表脚本的编辑能力的介绍.这一次的发布,我们将描述在Visual ...

  4. Ubuntu桌面版本和服务器版本之间的区别(转载)

    转载自:http://blog.csdn.net/fangaoxin/article/details/6335992 http://www.linuxidc.com/Linux/2010-11/297 ...

  5. angularjs + seajs构建Web Form前端(一)

    简介 Bootstrap是Twitter推出的一个用于前端开发的开源工具包,它由Twitter的设计师Mark Otto和Jacob Thornton合作开,是一个CSS/HTML框架. Angula ...

  6. CSS布局:Float布局过程与老生常谈的三栏布局

    原文见博客主站,欢迎大家去评论. 使用CSS布局网页,那是前端的基本功了,什么两栏布局,三栏布局,那也是前端面试的基本题了.一般来说,可以使用CSSposition属性进行布局,或者使用CSSfloa ...

  7. 贴近用户体验的jQuery日期选择插件

    分享一款贴近用户体验的jQuery日期选择插件.这是一款双日历jQuery日期选择时间插件pickerDateRange.效果图如下: 在线预览   源码下载 var dateRange = new ...

  8. 怎样设置一个DIV在所有层的最上层,最上层DIV

    怎样设置一个DIV在所有层的最上层,最上层DIV,其实很简单,只需要在这个DIV上使用这个样式即可,z-index:99999

  9. OP和DBA相关的一些有用资源

    最近国外blog上看到的一片资源分享博文,精而全,于是转帖分享 Must-Read Books List First of all, I would like to share a list of b ...

  10. bootstrap插件学习-bootstrap.tooltip.js

    先看bootstrap-tooltip.js的结构 var Tooltip = function ( element, options ){} // 构造器 Tooltip.prototype ={} ...