码迷,mamicode.com
首页 > Web开发 > 详细

PHP -- 面向对象

时间:2015-08-04 08:07:08      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

PHP – 面向对象

PHP – 面向对象

函数调用

class test {
    public function f1() {
        echo ‘you call me!‘;
    }
    public function f2() {
        f1();
    }
}
$t = new test();
$t->f2();                  // 报错

// public function f2() {  // 正确
//     self::f1();
// }

// public function f2() {  // 正确
//     static::f1();
// }

有 __clone 和无 __clone

一个值得注意的地方 __clone() cannot accept any arguments
  1. 直接赋值 (复制), 不会产生新的对象
    class test {
        public function __construct() {
            echo ‘ok‘;
        }
        public function __destruct() {
            echo ‘fail‘, ‘<br>‘;
        }
    }
    
    $a = new test();
    $b = $a;               // 指向同一个内存空间
    echo ‘<hr>‘;
    
    // ok
    // -----
    // fail
    
  2. clone 会生成一个新的对象, 但不会调用构造函数
    class test {
        public function __construct() {
            echo ‘ok‘;
        }
        public function __destruct() {
            echo ‘fail‘, ‘<br>‘;
        }
    }
    
    $a = new test();
    $b = clone $a;         // 指向不同的 内存空间
    echo ‘<hr>‘;
    // ok
    // ---------------
    // fail
    // fail
    
  3. __clone 调用析构函数
    class test {
        public function __construct() {
            echo ‘ok‘, ‘<br>‘;
        }
        public function __destruct() {
            echo ‘fail‘, ‘<br>‘;
        }
        public function __clone() {
            return self::__construct();
        }
    }
    
    $a = new test();
    $b = clone $a;         // 指向不同的 内存空间
    echo ‘<hr>‘;
    // ok
    // ok
    // -----
    // fail
    // fail
    

继承

<?php

class A {
    function foo() {
        if (isset($this)) {
            echo ‘this is defined (‘,  get_class($this), ‘)‘, ‘<br>‘;
        } else {
            echo ‘this is not defined‘, ‘<br>‘;
        }
    }
}

class B {
    function bar() {
        A::foo();
    }
}

$a = new A();                   // this 变成 A
$a->foo();
A::foo();
// this is defined (A)
// this is not defined


$b = new B();                   // this 变成 B
$b->bar();
B::bar();
// this is defined (B)
// this is not defined

继承的时候权限只能越来越大, 不能变小

class A {
    protected $a = ‘a‘;
    protected function f() {
        echo $this->a, ‘<br>‘;
    }
}

class B extends A{
    private function f() {
        echo $this->a, ‘<br>‘;
    }
}

$b = new B();
$b->f();                  // 报错

protected

class A {
    protected $a = ‘a‘;
    public function f() {
        echo $this->a, ‘<br>‘;
    }
}

class B extends A{
    public function f() {
        echo $this->a, ‘<br>‘;
    }
}

$b = new B();                   // 可以继承 protected
$b->f();

static

static 变量
所有实例化的实例化的类共享的变量, 其中一个改变了, 其他的也跟着改变

class stu {
    public static $fee;

    function f($fee) {
        self::$fee += $fee;
    }
}

static 方法
不可以操作 $this 变量, 使用 static 方法的情景, 一般的原则是某个方法中不包含 $this 变量

calss stu {
    static function func1() {
        static::func2();
    }
    static function func2() {
         ...
    }
}

调用: stu::func2();, stu::func1();

final

使用 finnal 的场景:

  1. 出于安全的考虑, 某个类的方法不允许被修改
  2. 不希望被其他的类继承

final 不能修饰成员属性 (变量)

final 方法, 表示此方法不能被重写

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called\n";
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()

final 类, 表示此类不能被继续被 extends

<?php
final class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   // 这里无论你是否将方法声明为 final,都没有关系
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
}
// 产生 Fatal error: Class ChildClass may not inherit from final class (BaseClass)

const

class  MyClass {
    const  constant  =  ‘constant value‘ ;
    function  showConstant () {
        echo   self :: constant  .  "\n" ;
    }
}
echo  $class :: constant . "\n" ;  // 自 PHP 5.3.0 起

后期绑定, 又叫延迟绑定

延迟绑定的意思, self 的绑定是运行时候计算, 看下面

class Par {
    public static function whoami() {
        echo ‘parent‘, ‘<br>‘;
    }

    public static function say() {
        self::whoami();
    }

    public static function say2() {
        static::whoami();
    }
}

class Sun extends Par {
    public static function whoami() {
        echo ‘sun‘, ‘<br>‘;
    }
}

Sun::say();                     // parent, 因为执行环境变成了 parent
Sun::say2();                    // sun, 保持静态

单例模式 instanceof

class mysql {
    public static $ins;

    private function __construct() {
        /* do something */
    }

    private function __clone () {}      // 禁止继承的类修改自身, 也可以使用 final

    public static function getIns() {
        if (!(self::$ins instanceof mysql)) {
            self::$ins = new self();
        }
        return self::$ins;
    }
}

$a = mysql::getIns();
$b = mysql::getIns();

var_dump ($a === $b);              // true

魔术方法

  1. __get
    class test {
        public $hello = ‘normal hello‘;
        public function __get($args) {
            if ($args == ‘hello‘) {
                echo ‘from get: hello‘;
            } else if ($args = ‘other‘) {
                echo ‘from get: other‘;
            }
        }
    }
    
    $t = new test();
    echo $t->hello, ‘<br>‘;       // normal hello, 如果存在不会调用 魔术方法
    echo $t->other;               // 不能调用, 调用魔术方法
    
  2. __set
    class test {
        public $hello = ‘normal hello‘;
        public function __set($k, $v) {
            echo ‘you want to set me! ‘, $k, ‘<br>‘;
            $this->$k = $v;
        }
    
    }
    
    $t = new test();
    $t->ttt = 222;
    echo $t->ttt;          // 可以设置
    
    $t->hello = ‘another hello‘;
    
    print_r($t);
    
    // you want to set me! ttt
    // 222
    
    // test Object
    // (
    //   [hello] => another hello
    //   [ttt] => 222
    // )
    
  3. __isset
    class test {
        public function __isset($v) {
            return false;
            .....
            return true;
        }
    }
    
    $t = new test();
    if (isset($t->value)) {
        echo ‘isset‘;
    } else {
        echo ‘noset‘;
    }
    
  4. __unset
    调用的属性不存在, 就会调用此函数, 主要用于友好操作
  5. __call
    无权调用的时候, 传递两个参数, (function_NAME, array function_ARGS)
    class test {
        public function func_empty() {
            echo ‘nothing here‘;
        }
    
        public function __call ($func, $args) {
            self::func_empty();
        }
    }
    
    $t = new test();
    
    class test {
        public function func_empty() {
            echo ‘nothing here‘;
        }
    
        public function __call ($func, $args) {
            print_r($args);
            self::func_empty();
        }
    }
    
    $t = new test();
    $t->abc(‘abc‘, ‘def‘);
    
    // Array ( [0] => abc [1] => def )
    
  6. __callStatic
    public static function  __callStatic ( $name ,  $arguments ) { ... }
    

重载 覆盖

覆盖: override 指的是子类覆盖父类的方法, 在 PHP 中, 如果 子类和父类的参数不一样会有警告
重载: redeclare 指的是同一个类中包含两个相同名字的方法, PHP 不支持

实现重载的方法

func_num_args()           返回数据的参数的个数
$arr = func_get_args()    让参数以数组的形式返回
func_get_arg(0)           返回第一个参数
func_get_arg(1)           返回第二个参数
public function f() {
    $arr = func_get_args();
    foreach($arr as $v) {
        ....
   }
}

魔术常量

__LINE__
__FILE__
__DIR__
__FUNCTION__
__CLASS__
__METHOD__

抽象类和接口

abstract

abstract class Car {
   abstract function func1();
}

class Fastcar extends Car {
   public function func1() {
     ...
   }
}
  1. 继承类必须实现抽象类的 所有 方法
  2. 抽象类可以有自己的属性
  3. 抽象类可以有自己的实现方法, 也叫具体方法, interface 没有
  4. 可以有 protected 方法, interface 不可以

interface

interface iUsb {
    public function f();
}
class phone implements iUsb {
    public function f() {
        ..
    }
}

定义规范

当多个类, 之间平级的, 有相同的方法, 但是实现不同

类可以实现多个接口, 接口可以实现多个接口

class t1 implements i1, i2, i3 { }
interface i1 extends i2, i2, i3 {}
  1. 继承类要实现 接口的全部方法
  2. interface 不能有 private 的方法
  3. interface 里面的属性只能是 常量
  4. interface 里面不能实现方法, 抽象类可以, (可以理解接口里面全都是抽象方法)
  5. interface 可以定义常量
class Monkey {
    public function climb() { ... }
}
interface iBirdable {
    public function fly();
}
interface iFishable {
    public function swim();
}
class NewMonkey extends Monkey implements iBirdable, iFishable {
    public function fly()  { ... }
    public function swim() { ... }
}

抽象类和接口的区别我不是 很熟悉 T_T, mark 个 todo 以后再来补充

  1. 如果要创建一个模型, 这个模型将由一些紧密的对象采用, 就可以使用抽象类. 如果要创建由一些不相关对象采用的功能, 使用接口
  2. 如果必须从多个来源继承行为, 就使用接口. 接口可以实现多个, 不可以继承多个抽象类
  3. 如果所有的类会有共享一个公共的行为实现, 就使用抽象类, 并在其中的实现该行为, 在接口中无法实现具体方法

命名空间

如果文件 1 有 test 对象, 文件 2 也有 test 对象
在文件 3

require ‘file1.php‘;
require ‘file2.php‘;

那么就会出现冲突

test1.php

<?php
namespace test\file1;
class test {
    public $val = ‘this is file 1‘;
}

test2.php

<?php
namespace test\file2;      # 也可以使用别的命名空间 ...\...\...\...
class test {
    public $val = ‘this is file 2‘;
}

test.php 用于加载访问

<?php

require ‘test1.php‘;
require ‘test2.php‘;

$t1 = new test\file1\test();
$t2 = new test\file2\test();

echo $t1->val, ‘<br>‘;        // this is file1
echo $t2->val, ‘<br>‘;        // this is file2

use test\file1 as file1;
use test\file2 as file2;

$t3 = new file1\test();
$t4 = new file2\test();

echo $t3->val, ‘<br>‘;        // this is file1
echo $t4->val, ‘<br>‘;        // this is file2

其他对象方法

class_alias(class_name, new_classname)
get_class (OBJ)
$arr = get_declared_classes()       # 返回已经定义了的类
get_parent_class (OBJ)
interface_exists (INTER)            # 是否存在接口
method_exists (OBJ, FUNC_NAME)      # 是否存在某个方法

自动加载

function  __autoload ( $class_name ) {
    require  $class_name  .  ‘.php‘ ;
}

$obj   = new  MyClass1 ();      // 自动会调用上面的哪个函数, 参数名是 MyClass1
$obj2  = new  MyClass2 ();      // 自动会调用上面的哪个函数, 参数名是 MyClass2

为什么函数里面的 require class 的生活周期可以到外层, 原因像下面的,
__autoload 被执行之后, 就相当于把函数里面的代码展示出来

function well() {
    function test() {
        echo ‘inside ‘, ‘<br>‘;
    }
}
well();      // 一定要先调用
test();      // inside
__autoload 的实现
spl_autoload_register —— 注册给定的函数作为 __autoload 的实现
function func() {
    require ‘...‘;
}
spl_autoload_register(func);

TODO SPL 函数

PHP -- 面向对象

标签:

原文地址:http://www.cnblogs.com/sunznx/p/4700900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!