php面向对象视频笔记之第三章(面向对象类特性)

一、静态属性和静态方法

1、定义
1-1、用static关键字修饰的属性称为静态属性
1-2、用static关键字修饰的方法称为静态方法
2、特性
2-1、静态属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此这类属性
或方法也称为“类属性”或“类方法”;
2-2、静态属性和方法,在类被调用(类被创建或者类中的任何静态成员被调用)时创建;
2-3、类的调用不代表类被实例化;
2-4、静态属性,在内存中只有一份,为所有的实例共有;
2-5、静态方法不能调用非静态属性,也不能使用$this获取非静态属性的值。
3、使用
3-1、如果访问控制权限允许,可不必创建该类对象而直接使用类名加两个冒号“::”调用
静态属性和静态方法;
3-2、调用语法:类名[或self]::静态属性名(静态方法名),而且在类内部强烈建议用
slef:: 来调用;
3-3、当一个类中有非静态方法被 self:: 调用时,系统会自动将这个方法转化为静态方法;
3-4、静态方法不能调用非静态属性,也不能使用 $this 获取非静态属性的值。
3-5、注意:在静态方法里,只调用静态属性和静态方法。


二、关键字 final (php5.3以上才引入)

1、使用 final 的场景
1-1、如果我们不希望一个类被继承,可使用 final 来修饰这个类;
1-2、如果我们不希望一个类的方法被重写,可使用 final 来修饰这个方法;
1-3、在 php 中,final 可修饰类,也可以修饰类的方法,但不能修饰属性。


三、单例模式

1、单例模式
单例模式(也叫单件模式)是让一个类在内存中仅有一个实例。
2、单例模式的优势
单例模式保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,
从而更加高效地利用系统资源。
3、技术点
3-1、不能用 new 类名的方式来创建一个对象;

';
   }
   //获取Db类的唯一实例对象
   static function getDb(){
      if(self::$db == null || !(self::$db instanceof self)){//判断其是否为类的实例。(后半句就可以判断了)
	     self::$db = new self();//new Db();不建议
	  }
	  return self::$db;
   }

   public function test(){
      echo '我是test方法.
'; } } //$db = new Db();//构造方法私有化不能使用new构造新对象。 Db::getDb(); Db::getDb();//不管调用多少次此函数都只初始化一个对象。 $db = Db::getDb(); Db::$db = 1; //注意此处的$db只是个普通变量,而Db::$db是类的静态变量。 //(避免被改值可将类中此变量访问权限改为private) $db->test(); print_r($db); echo '
'; print_r(Db::$db); echo '
'; print_r(Db::getDb()); echo '
'; Db::getDb()->test(); ?>

php面向对象视频笔记之第三章(面向对象类特性)_第1张图片

3-2、禁止类的构造方法被重写;

';
   }
   //获取Db类的唯一实例对象
   static function getDb(){
      if(self::$db == null || !(self::$db instanceof self)){//判断其是否为类的实例。(后半句就可以判断了)
	     self::$db = new self();//new Db();不建议
	  }
	  return self::$db;
   }

   public function test(){
      echo '我是test方法.
'; } } class MyDb extends Db{ /* public function __construct(){ //parent::__construct(); //还是不能使用父类的private修饰的构造方法。 echo 'MyDb类有新对象创建了
'; } public function test1(){ echo '我是子类中的test1方法.
'; } */ public static function test1(){ echo '我是子类中的test1方法.
'; } } //$MyDb = new MyDb(); //$MyDb1 = new MyDb(); $MyDb = MyDb::getDb(); $MyDb1 = MyDb::getDb(); //MyDb::getDb()->test1();子类由于构造方法不能重写因此未被实例化, //而是由父类实例化的对象所以不能访问子类的方法。一般使用static来 //声明方法,而不是重写父类的方法,因为不会被调用。 MyDb::getDb()->test(); MyDb::test1();

3-3、禁止类的实例被外界克隆;

';
   }

   //当有当前类的对象被克隆时调用
   private function __clone(){//私有化则禁止在类外被调用。
      echo '有Db类的对象被克隆了';
   }

   //获取Db类的唯一实例对象
   static function getDb(){
      if(self::$db == null || !(self::$db instanceof self)){//判断其是否为类的实例。(后半句就可以判断了)
	     self::$db = new self();//new Db();不建议
	  }
	  return self::$db;
   }

}

$db = Db::getDb();
/*把魔术方法__clone()私有化即可阻止下面的调用。
$db1 = clone $db;//属性和方法相同,内存地址不同。

if($db == $db1){//true
   echo '
克隆出来的对象和被克隆对象具有相同的属性和方法.
'; } if($db === $db1){//false echo '是同一个对象
'; }else{ echo '不是同一个对象
'; } */ ?>

四、常量关键字 const

1、const 定义常量语法以及注意点
1-1、const 定义常量语法:const 常量标识符 = 常量值;
1-2、const 关键字一般在类的声明里定义常量时使用;在php5.3.0以后,可以使用const关键
字在类定义的外部定义常量。
1-3、const 定义的常量默认为大小写敏感,通常常量标识符总是大写的,而且也建议在开发
过程中使用大写。
2、const 与 define 都可以定义常量,但他们又不同
2-1、const一般用于类成员常量的定义,一经定义,不可修改。define不可用于类成员变量的
定义,一般用于定义全局变量;
2-2、const不能在条件语句中定义常量;
2-3、const采用一个普通的常量名称,define可以采用表达式作为名称;
2-4、const只能接受静态的标量,而define可以采用任何表达式;
2-5、const定义的常量是大小写敏感的,而define可通过第三个参数(为true表示大小写不敏感)
来指定大小写是否敏感。
const TEST = 'test';//等同于 define('TEST','test');
class Person{
  const NAME = 'lisi';
  const name = 'wangwu';//不建议使用小写字母定义常量(虽然区分大小写)


  public function test(){
     //访问方式
     echo self::NAME,'
';
     echo self::name,'
';
     echo TEST,'
';
  }
}


$n = 'T'.mt_rand(1,999);//define可以采用表达式作为名称
define($n, 12);
echo constant($n);//获取常量值


define('NAME','lisi',true);//define第三个参数为true时代表不区分大小写。
echo NAME,'
'; <=> echo name,'
';


五、延迟绑定 static

1、延迟绑定(后期静态绑定)
1-1、在php5.3中加入了一个新特性(后期静态绑定),该特性最明显的标志就是新关键字static,
用法类似于self;
1-2、“后期静态绑定”的意思是说,static::不再被解析为定义当前方法所在的类,而是在实际运行时
计算的。因此也称之为执行期绑定。比如当一个子类继承了父类的静态属性或方法的时候,它的值并不
能被改变,有时不希望看到这种情况。
class Person{
  static $name = 'lisi';
  const AGE = 22;
  public static function intro(){
    echo 'My name is '.self::$name,'
';
    echo 'My age is '.self::AGE,'
';
  }
  public static function intro1(){//使用static::实现延迟绑定功能。
    echo 'My name is '.static::$name,'
';
    echo 'My age is '.static::AGE,'
';
  }
}
class Stu extends Person{
   static $name = 'wangwu';
   const AGE = 20;
   public static function intro(){//重写父类的方法。
     echo 'My name is '.self::$name,'
';
     echo 'My age is '.self::AGE,'
';
   }
}


Person::intro();
echo '


';
Stu::intro();
echo '
';
Stu::intro1();
结果如下:

php面向对象视频笔记之第三章(面向对象类特性)_第2张图片

六、魔术方法(函数)和魔术常量

1、php中的魔术方法(函数)
__construct(),__destruct(),__get(),__set(),__isset(),__unset(),__clone()
等方法在php中被称为“魔术方法”(Magic methods)。在命名自己的类方法是不
能使用这些方法名,除非是想使用其魔术功能。
2、各种魔术方法简介
2-1、__construct构造方法,当一个对象创建时调用此方法;
2-2、__destruct析构方法,php将在对象被销毁前调用此方法。
2-3、__get($property)当调用一个未定义的属性或没有声明的属性时调用此方法;
2-4、__set($property,$value)给一个未定义的属性或没有声明的属性赋值时调用此方法;
2-5、__isset($property)当对一个未定义的属性或没有声明的属性调用isset()函数时调用此方法;
2-6、__unset($property)当对一个未定义的属性或没有声明的属性调用unset()函数时调用此方法;
2-7、这里的没有声明包括当使用对象调用时,访问控制修饰符为protected或private的属性
(即没有权限访问的属性);
2-8、__clone()
php中的对象赋值是使用的引用赋值,如果想复制一个对象则需要使用clone方法,在调用此方法时
对象会自动调用__clone魔术方法;
2-9、__toString()
__toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时如果类没有实现此
方法,则无法通过echo打印对象,否则显示:Catchable fatal error:Object of class test could
not be converted to string in。此方法必须返回一个字符串。
2-10、__sleep()与__wakeup()
__sleep()在对象被serialize之前被调用。若对象比较大,想删减一东东再序列化,可考虑下此函数。
返回值是包含这个对象需要序列化的属性数组。
__wakeup()在对象被unserialize时被调用,常用于做一些对象的初始化工作。
2-11、__invoke()
当尝试以调用函数的方式调用一个对象时,__invoke方法会被自动调用。(php5.3.0以上版本有效)
2-12、__call()
__call($method,$arg);当调用一个未定义的方法时调用此方法,这里的未定义的方法包括没有访问权限
的方法。
2-13、__callStatic()
它的工作方式类似于__call()魔术方法,__callStatic()是为了处理静态方法调用,并且必须被声明为静态的。
2-14、__autoload()
__autoload函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在php出错失败前
有了最后一个机会加载所需的类。
3、魔术常量

php面向对象视频笔记之第三章(面向对象类特性)_第3张图片


七、抽象类(abstract class)

1、抽象类与抽象方法
1-1、php5开始支持抽象类和抽象方法,用abstract修饰的类表示这个类是一个抽象类,用abstract修饰的方法
表示这个方法是一个抽象方法。
1-2、抽象类不能被实例化。
1-3、抽象方法只能声明,不能定义其具体的功能实现。
1-4、任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象类。
2、抽象类的继承
2-1、抽象类继承另外一个抽象类时,不用重写其中的抽象方法。
2-2、抽象类中,不能重写抽象父类的抽象方法。这样的用法,可以理解为对抽象类的扩展。
2-3、继承抽象类的非抽象类必须实现抽象类中的所有抽象方法。
3、抽象类的应用
3-1、模板模式又叫模板方法模式,在一个类中定义一个算法的骨架,而将一些步骤延迟到子类中。
3-2、模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

八、类的自动加载

1、为什么要用类的自动加载?
1-1、在系统开发过程中,不可能把所有的类都写在一个php文件中,当在一个php文件中需要调用另一个文件中
声明的类时,就需要通过include或require把这个文件引入。
1-2、在类文件众多的项目中,要将所需类的文件都逐个引入,是一个很让人头疼的工作。那么我们能不能在用
到什么类的时候,再把这个类所在的php文件引入呢?
2、__autoload()魔术方法实现
2-1、在php5中,可以定义一个__autoload()函数,它会在试图使用尚未被定义的类时自动调用,通过调用此函数,
脚本引擎在php出错失败前有了最后一个机会加载所需的类。
2-2、__autoload($className)函数接收的一个参数,就是你想加载的类的类名,所以你做项目时,在组织定义类的
文件名时,需要按照一定的规则,最好以类名为中心,也可以加上统一的前缀或后缀形成文件名。
2-3、set_include_path().是在脚本里动态地对php.ini中include_path进行修改的。动态设置包含目录(预定义
include和require的路径范围)。//在原先路径基础上通过路径分割符加上新目录格式如下。
加载lib目录下的类:set_include_path(get_include_path().PATH_SEPARATOR."lib/");
直接在__autoload($className)内部加上 include $className.'.php';即可成功调用根目录和lib目录下的类。
3、spl_autoload_register()
3-1、此函数的功能就是把函数注册至SPL的__autoload函数栈中,并移除系统默认的__autoload()函数。

function __autoload($className){
   echo '__autoload class:',$className,'
'; } function classLoader($className){ echo 'SPL load class:',$className,'
'; } spl_autoload_register('classLoader'); new Test();//结果:SPL load class:Test
3-2、spl_autoload_register()可以调用多次。它实际上创建了autoload函数的队列,按定义时的顺序逐个执行。而
__autoload()只可以调用一次。
3-3、如果注册的自动加载函数是一个类的方法,则参数可以传递为一个数组,格式为 spl_autoload_register(array(类名,方法名));
set_include_path(get_include_path().PATH_SEPARATOR."lib/");
class autoLoad{
  public static function loadClass($className){
     echo 'autoLoad 中的 loadClass '.$className,'
'; include $className.'.php'; } } spl_autoload_register(array('autoLoad','loadClass')); new Test(); //根目录下的类。 new Test1();//lib目录下的类。
推荐使用类方法加载。

你可能感兴趣的:(PHP)