PHP5面向对象中的基本概念

PHP5相对于PHP4一个非常大的改变就是OOP,甚至可以说几乎所有OOP的内容在PHP5中都被改变了。

 

【基本概念】

1.问:OOP与面向过程编程最大的区别?

   答:在OOP中,数据和代码都是被绑定到一个实体当中(常量及静态常量变量除外,因为它们是被绑定到类上的),这个实体就叫做对象。OOP把一个问题切割成很多的对象,每个对象都是一个问题的实体,它们之间相互独立,拥有各自的属性和方法。对其他类来说,那些公共方法可以看成这个类的一个接口。

 

2.对象的创建--new关键字

   注意点:1.与C++等语言不同,PHP在创建子对象的时候并不会先创建父对象,即不会调用父类的构造函数

              2.与PHP4不同,PHP5中用new关键字创建对象返回的是一个句柄(可以理解成表示该对象的ID),对属性的修改即为直接对内存地址中的值进行操作。(PHP4中new创建对象的返回值为对象的一份拷贝)

 1     class Person{
 2         public $name;
 3         function __construct($name=""){
 4             $this->name = $name;
 5             print "成功创建一个Person对象";
 6         }
 7     }
 8     class Student extends Person{
 9         public $id;
10         function __construct($id="",$name=""){
11             $this->id = $id;
12             $this->name = $name;
13             print "成功创建一个Student对象";
14         }
15     }
16     
17     $Yao = new Student("","Yao");
18     var_dump($Yao);

输出如下:

成功创建一个Student对象  object(Student)#1 (2) { ["id"]=> string(0) "" ["name"]=> string(3) "Yao" }

 

3.静态和常量

  ① 和常规属性不同,静态属性是属于类本身而不属于任何类的实例。在类的内部,你可以通过特殊的类名self(表示一个方法所属类的缩写)访问它,在类的外面,你可以通过类名::method()直接访问;静态方法亦是如此。常量用const定义,访问方法同静态属性。看下面这个例子:

 1 class Person{
 2     static function sayHello(){
 3         print "Hello ";
 4         self::sayName();
 5     }
 6     static function sayName(){
 7         print "Jim";
 8     }
 9 }
10 Person::sayHello();

结果如下:

Hello Jim

因为静态方法不被限制到任何特定的对象,所以你可以不创建对象实例就可以通过class_name::method()语法调用它。同时,你也可以在任何一个实例中通过$this->method()访问这些静态方法,但是在这里$this是没有定义的,如果把self::sayName()改成$this->sayName(),则会提示

Hello 
Fatal error: Using $this when not in object context in...

  ②静态变量还有个特点就是:可以被初始化,但是初始化只能在第一次static申明的时候发生,而且只能在申明它的函数中访问到!

 

4.多态

同一个操作用于不同类的实例,将产生不同的执行结果。或者说不同的对象收到相同的消息时,将收到不同的结果。(一大优点是能省去很多的条件控制语句--如if,从而编写出可扩展的健壮的代码)。看下面的例子:  

 1     class Cat{
 2         function miao(){
 3             print "miao";
 4         }
 5     }
 6     class Dog{
 7         function wuff(){
 8             print "wuff";
 9         }
10     }
11     function printTheRightSound($obj){
12         if( $obj instanceof Dog ){
13             $obj->wuff();
14         }else if( $obj instanceof Cat ){
15             $obj->miao();
16         }else{
17             print "Error: unknown kind of object";
18         }
19         print "\n";
20     }
21     
22     printTheRightSound(new Dog());
23     printTheRightSound(new Cat());

很容易看出这个例子是不能扩展的。假如要再增加3种动物,你不得不在printTheRightSound()中增加3个else if模块以便检查是哪一种动物。

而多态可以用继承来解决这个问题,代码如下:

 1     abstract class Animal{
 2         abstract function makeSound();
 3     }
 4     class Dog extends Animal{
 5         function makeSound(){
 6             print "wuff";
 7         }
 8     }
 9     class Cat extends Animal{
10         function makeSound(){
11             print "miao";
12         }
13     }
14     function printTheRightSound($obj){
15         if($obj instanceof Animal){
16             $obj->makeSound();
17         }else{
18             print "Error: unknown kind of object";
19         }
20         print "\n";
21     }
22     
23     printTheRightSound(new Dog());
24     printTheRightSound(new Cat());

 

5. 抽象类和接口

   上段代码使用abstract关键字定义父类能使你不需要在Animal的makesound()方法中提供没有意义的函数执行体。

    区别:抽象类不是一个具备完整功能的类而只是为了被继承。抽象类中可以包含成员变量及具体的方法,只要有一个方法被定义成abstract,整个类就需要被申明成abstract。而接口是用来弥补PHP中类之间无法实现多重继承这一问题的,接口默认是public的,不能添加访问修饰符,里面只能包含常量以及函数申明(不需要申明成abstract,默认就是这货),任何一个"implements"该接口的类必须实现接口中的所有方法(除非是抽象类)--可以用instanceof进行判断,接口与接口之间允许多重继承,但是接口A与B之间不允许有同名的方法及常量。

 

6.instanceof

上面的instanceof是一个二元逻辑运算符,代替PHP4中的is_a()内置函数,同时,这个函数还可以用来检查类是否所继承的接口。代码如下:

 

 1     interface drink{
 2         function  heshui();
 3     }
 4     interface sleep{
 5         function shuijiao();
 6     }
 7     
 8     abstract class Animal{
 9         abstract function makeSound();
10     }
11     class Dog extends Animal implements drink{
12         public $name = "Dog";
13         function makeSound(){
14             print "wuff";
15         }
16         function heshui(){
17             print $this->name." drink";
18         }
19     }
20     class Cat extends Animal implements sleep{
21         static $name = "Cat";
22         function makeSound(){
23             print "miao";
24         }
25         function shuijiao(){
26             print self::$name." sleep";
27         }
28     }
29     function printTheRightSound($obj){
30         if($obj instanceof sleep){
31             $obj->shuijiao();
32         }else{
33             print $obj->name . " has not implements the interface";
34         }
35         print "\n";    
36     }
37     
38     printTheRightSound(new Dog());
39     printTheRightSound(new Cat());

结果:

Dog has not implements the interface
Cat sleep

注:这里可以发现,用$this->访问属性的时候,不需要$符号,而用self::访问的时候,还是需要$符号的。。。我的理解是,只有属于对象的属性是不需要加上$符号的,这个不知道对不对。。。

 

7.final关键字

 写在函数前面,该函数在继承时不能被重载;写在类前面,该类不能被继承。

 

8.异常处理(try-throw-catch)

处理过程:当try{}结构中抛出一个异常(异常只能是一个继承自Exception的一个object,不能是字符串或者整形等),首先达到第一个catch()并执行instanceof比较,如果返回true,PHP进入catch块,如果返回false,PHP检查下一个catch语句,一旦进入一个catch语句,下面的catch语句将不再进入。抛出异常后,try块中之后的语句将不再执行。代码如下:

 1     class NullHandleException extends Exception{
 2         function __construct($message){
 3             parent::__construct($message);
 4         }
 5     }
 6     function printObject($obj){
 7         if($obj == NULL){
 8             throw new NullHandleException("printObject received NULL object");
 9         }
10         print $obj."\n";
11     }
12     class MyName{
13         function __construct($name){
14             $this->name = $name;
15         }
16         function __toString(){
17             return $this->name;
18         }
19         private $name;
20     }
21     try{
22         printObject(new MyName("Bill"));
23         printObject(NULL);
24         printObject(new MyName("Tom"));
25     }catch(NullHandleException $e){
26         print "first_level:" . $e->getMessage();
27     }catch(Exception $e){
28         print "second_level" . $e->getMessage();
29     }

输出:

Bill
first_level:printObject received NULL object

__toString()用来定义new关键字的返回值(未定义的话,返回object(Student)#1),但现在只能被print和echo调用

posted @ 2012-11-28 18:04  Abel1990  阅读(236)  评论(0编辑  收藏  举报