PHP面向对象编程笔记

面向对象编程的确缺点:由于面向对象的代码在执行的过程中比面向过程的代码繁琐,所以面向对象的执行效率略低于面向过程,不过这种低是几乎可以忽略的。

 

封装,继承,多态。

 

class className{

         public$a;

         publicfunction abc(){

                   ...

         }

}

 

无论是类属性还是类方法,前面都是要有关键字修饰的,private、protect、public。

 

类属性与普通属性的一个很大的区别是,类属性在声明时赋予初始值,且这个初始值要么为空要么为常数,不能是一个表达式,public $a = 1+2;这样写就是不对的。

除了声明类属性之外的其它代码都必须放在类方法中。

 

我们声明的类不能跟php系统的类重名。

unset($object);删除一个类。

为了编程的规范和方便,类最好单独分开,放在以类名为文件名的文件里,用的时候require一下。

类名不区分大小写,对象名区分大小写,顺便说一句,数组里面的键名是区分大小写的。

函数名不区分大小写。

class className{

         public$a = 0;

         publicfunction abc(){

                   $this->a= 1;

         }       

}

方法中$this->a = 1可以修改类的属性$a。

类方法之间是可以互相调用的。

构造函数__construct是在实例化对象时最先调用的函数。

析构函数__destruct是在销毁对象时调用,不能接收任何参数。

魔术函数__autoload()

PHP在魔术函数__autoload()方法出现以前,如果你要在一个程序文件中实例化100个对象,那么你必须用include或者require包含进来100个类文件,或者你把这100个类定义在同一个类文件中——相信这个文件一定会非常大。

但是__autoload()方法出来了,以后就不必为此大伤脑筋了,这个类会在你实例化对象之前自动加载制定的文件。

下边我们通过一个例子来看一下,具体的使用方法,并在稍后说明使用PHP魔术函数__autoload应该注意些什么。

代码如下

复制代码

 //定义一个类ClassA,文件名为ClassA.php
class ClassA{
 public  function __construct(){
  echo "ClassA load success!";
 }
}

 //定义一个类ClassB,文件名为ClassB.php,ClassB继承ClassA
class ClassB extends ClassA {
 public function __construct(){
  //parent::__construct();
  echo "ClassB load success!";
 }
}

定义两个测试用的类之后,我们来编写一个含有__autoload()方法的PHP运行程序文件如下:

代码如下

复制代码

 function __autoload($classname){
 $classpath="./".$classname.'.php';
 if(file_exists($classpath)){
  require_once($classpath);
 }
 else{
  echo 'class file'.$classpath.'not found!';
 }
}
 
$newobj = new ClassA();
$newobj = new ClassB();

这个文件的运行是一点问题都没有的,可见autoload是多么的好用啊。

__autoload函数是在需要引用其它类的那个文件里面编写的单独的函数,不是放在类中编写的,注意不要混淆,而且还要注意,类名和文件名必须一致。

instanceof关键词可以用来查看一个特别的对象是不是继承自某个类,也可以用来查看接口的继承关系。

if ($obj instanceof $father) …

注意,类名不放在引号里。

 

当子类与父类都有构造函数时,php优先调用子类的构造函数,假如调用到了子类的构造函数,就不再调用父类的构造函数。(其实这样也可以理解为子类对父类构造函数的重写)

final修饰的方法不可以被重写。

final修饰的类不可以被继承。

重写和重载是不同的:函数中的变量个数相同叫重写(变量个数相同,方法体不同),变量个数不同叫重载。

Private:只能在本类内部使用。

Protect:可以在子类中使用。

Public:到处都能用。

PHP中调用类方法时->和::的区别:
在类里面的时候,$this->func()和self::func()没什么区别。

在外部的时候,->必须是实例化后的对象使用;而::可以是未实例化的类名直接调用。

举个例子:

class Mytest{

   function ccc($str){

       echo $str;

    }

}

Mytest::ccc("123456");

$object = new Mytest();

$object->ccc("123456");

 

静态属性:类里的静态属性相当于函数中的静态变量。也就是说,一个静态属性可以在每次被方法调用之后记住其新值,也就是说,静态属性的值是可以被方法改变的。

static $n;

静态属性和标准属性的区别是,我们不能在类里用$this访问他,而是应该使用self后跟范围操作符(::)  self::$counter++

 

类常数:类常数可以被类及其子类的全部实例访问,他的值是不可改变的。(不用$符号)

const PI = 3.14;

 

PHP的静态方法:
静态方法的规则和静态变量是相同的。使用ststic关键字可以将方法标识为静态方法,通过类的名称和作用域限定操作符::可以访问静态方法。

静态方法和非静态方法之间有一个很重要的区别,就是在调用静态方法时,我们不需要创建类的实例。

静态方法可以不实例化,直接调用,可以被重写。

Program List:用类名作为参数

用类名作为参数可以解决非继承的静态问题。

01

<?php

02

class Fruit {

 

03

    public static $category = "I'm fruit";

04

     

 

05

    static function find($class)

06

    {

 

07

        $vars = get_class_vars($class) ;

08

        echo $vars['category'] ;

 

09

    }

10

}

 

11

 

12

class Apple extends Fruit {

 

13

     public static $category = "I'm Apple";

14

}

 

15

 

16

Apple::find("Apple");

 

17

?>

程序运行结果:

1

I'm Apple

Program List:重写基类方法

在派生类重写基类的方法。

01

<?php

02

class Fruit

 

03

{

04

    static function Foo ( $class = __CLASS__ )

 

05

    {

06

        call_user_func(array($class, 'Color'));

 

07

    }

08

}

 

09

 

10

class Apple extends Fruit

 

11

{

12

    static function Foo ( $class = __CLASS__ )

 

13

    {

14

        parent::Foo($class);

 

15

    }

16

 

 

17

    static function Color()

18

    {

 

19

        echo "Apple's color is red";

20

    }

 

21

}

22

 

 

23

Apple::Foo(); // This time it works.

24

?>

程序运行结果:

1

Apple's color is red

Program List:静态数组的使用

静态和const作用域都可以用::操作符访问,如果你想使用::操作符访问数组,你需要事先将数组声明为静态。

01

<?php

02

class Fruit

 

03

{

04

    static $color = array('color1' => 'red', 'color2' => 'yellow');

 

05

}

06

 

 

07

class Apple

08

{

 

09

    public function __construct()

10

    {

 

11

        var_dump(Fruit::$color);

12

    }

 

13

}

14

 

 

15

class Banana

16

{

 

17

  public function __construct()

18

  {

 

19

    Fruit::$color = FALSE;

20

  }

 

21

}

22

 

 

23

new Apple();    // prints array(2) { ["color1"]=> string(3) "red" ["color2"]=> string(6) "yellow" }

24

echo '<br />';

 

25

new Banana();

26

new Apple();    // prints bool(false)

 

27

?>

程序运行结果:

1

array(2) { ["color1"]=> string(3) "red" ["color2"]=> string(6) "yellow" }

2

bool(false)

Program List:再来一个单例模式

Static真的很酷,下面的程序演示了如何获得一个已经存在的实例。

01

<?php

02

class Singleton {

 

03

 

04

    private static $instance=null;

 

05

    private $value=null;

06

 

 

07

    private function __construct($value) {

08

        $this->value = $value;

 

09

    }

10

 

 

11

    public static function getInstance() {

12

        if ( self::$instance == null ) {

 

13

            echo "<br>new<br>";

14

            self::$instance = new Singleton("values");

 

15

        } 

16

        else {

 

17

            echo "<br>old<br>";

18

        }

 

19

        return self::$instance;

20

    }

 

21

 

22

}

 

23

 

24

$x = Singleton::getInstance();

 

25

var_dump($x); // returns the new object

26

$y = Singleton::getInstance();

 

27

var_dump($y); // returns the existing object

28

?>

程序运行结果:

1

new

2

object(Singleton)#1 (1) { ["value:private"]=> string(6) "values" }

 

3

old

4

object(Singleton)#1 (1) { ["value:private"]=> string(6) "values" }

 

抽象类

抽象类不能被实例化,只能被继承。

abstract class className{}

抽象类中通常也会有抽象方法,abstract public function name()

抽象方法只有声明,没有方法体。

哪怕一个类中只有一个抽象方法,那么这个类也必须定义成抽象类。

抽象类中可以有非抽象方法。

__toString();当一个类被当做string类型的时候,就会自动调用__toString()方法,比如:
$a = new someClass();

echo $a;

__toString()可以作为一个简单的调试工具。

要是没有__toString()方法的话,直接echo这个类,是要报错的。

 

接口

接口中的所有方法都必须是public的,且子类必须实现接口中的所有方法,接口中的方法有声明、有参数,但是没有方法体。

定义接口:interface isomething

作为惯例,接口的名字往往以i开头

子类继承接口:class className implements isomething

 

复制和克隆

由于php是使用引用来传递参数,而不是使用值,所以,当我们创建一个对象的副本的时候,php其实只是创建了这个对象的一个引用,而不是复制整个新对象。换句话说,两个变量会指向相同的东西,通过一个对象对其值的修改会影响到另外一个对象。

如果我们真的需要两个分开的、完全独立的对象,就需要创建一个对象的克隆。

$b = clone $a;

这个时候会出发class中的__clone()方法(假如类中定义了__clone()方法的话)。

 

traits(PHP 5.4版本)

以一种迂回的方式解决php不能多继承的问题。

定义一个trait:
trait tSomeTrait{

         publicfunction someName(){

         …

}

}

 

使用trait:

Class someClass{

         UsetSomeTrait;

}

可以use多个trait,相当于require代码的效果。

trait来的方法、继承来的方法、类自身方法优先级问题:

当上述三种情况出现同名方法时,优先级为:类自身方法> trait来的方法>继承来的方法

 

命名空间namespace(php 5.3版本)

可以解决多个类名相同而导致的冲突问题。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值