PHP学习之类与对象(三)

抽象类

PHP5支持抽象类和抽象方法。
  • 定义为抽象的类不能被实例化;
  • 任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的;
  • 被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现;
  • 继承一个抽象类时,子类必须定义父类中的所有抽象方法另外,这些方法的访问控制(public/protected/private)必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
  • 此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 这也适用于 PHP 5.4 起的构造函数。在 PHP 5.4 之前的构造函数声明可以不一样的。

例2:

对象接口

  1. 使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容
  2. 接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的
  3. 接口中定义的所有方法都必须是公有,这是接口的特性。
接口的实现(implements)
  • 实现一个接口,使用 implements 操作符
  • 类中必须实现接口中定义的所有方法,否则会报一个致命错误。
  • 类可以实现多个接口,用逗号来分隔多个接口的名称
  • 实现多个接口时,接口中的方法不能有重名
  • 接口也可以继承,通过使用 extends 操作符。
  • 类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。
  • 接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖
补充: str_repeat()函数   把字符串重复指定的次数。
           语法:str_repeat( string, repeat) 其中string是必须的,规定要重复的字符串。
                                                                    repeat也是必须的,规定字符串将被重复的次数,必须大于等于0.

           返回值:返回被重复的字符串。
可扩充的接口:
继承多个接口:
使用接口常量:

Trait

php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性。
用法:通过在类中使用use 关键字声明要组合的Trait名称具体的Trait的声明使用Trait关键词 Trait不能实例化。
再测试Trait、基类和本类对同名属性或方法的处理,如下代码:

所以:Trait中的方法或属性会覆盖基类中的同名的方法或属性,而本类会覆盖Trait中同名的属性或方法。

一个类可以组合多个Trait,通过逗号相隔,如use trait1,trait2

当在不同的trait中,有着同名的方法或属性时,会产生冲突,可以使用insteadof或 as进行解决,insteadof 是进行替代,而as是给它取别名。

<?php
header("Content-type: text/html; charset=utf-8");
//使用trait关键字声明一个trait Dog,注意trait不能像类一样实例化
trait trait1{
 public function eat(){
  echo "This is trait1 eat!" . "<br/>\n";
 }
 public function drive(){
  echo "This is trait1 drive!" . "<br/>\n";
 }
}
trait trait2{
 public function eat(){
  echo "This is trait2 eat!" . "<br/>\n";
 }
 public function drive(){
  echo "This is trait2 drive!" . "<br/>\n";
 }
}
class cat{
 use trait1, trait2{
  //使用insteadof将trait1中的eat,drive方法分别替代trait2中的同名方法
  trait1::eat insteadof trait2;
  trait1::drive insteadof trait2;
 }
}
class dog{
 use trait1, trait2{
  //使用insteadof将trait1中的eat,drive方法分别替代trait2中的同名方法
  trait1::eat insteadof trait2;
  trait1::drive insteadof trait2;
  //使用as将trait2中同名方法eat和drive分别起别名为eaten和driven
  trait2::eat as eaten;
  trait2::drive as driven;
 }
}
$cat = new cat();
$cat -> eat();//This is trait1 eat!
$cat -> drive();//This is trait1 drive!
$dog = new dog();
$dog -> eat();//This is trait1 eat!
$dog -> drive();//This is trait1 drive!
$dog -> eaten();//This is trait2 eat!
$dog -> driven();//This is trait2 drive!
?>
as 还可以修改方法的访问控制。


Trait也可以互相组合,还可以使用抽象方法,静态属性,静态方法等,实例如下:

<?php
header("Content-type: text/html; charset=utf-8");
trait Cat{
 public function eat(){
  echo "This is Cat eat!". "<br/>\n";
 }
}
trait Dog{
 use Cat;
 public function drive(){
  echo "This is Dog drive!". "<br/>\n";
 }
 //定义抽象方法getName(必须在子类中实例化)
 abstract public function getName();
 public function test(){
  static $num = 0;
  $num ++;
  echo $num . "<br/>\n";
 }
 //定义trait Dog的静态方法say
 public static function say(){
  echo "This is dog say!". "<br/>\n";
 }
}
class animal{
 use Dog;
 public function getName(){
  echo "This is animal name!". "<br/>\n";
 }
}
$animal = new animal ();
$animal -> getName();//This is animal name!
$animal ->eat();//This is Cat eat!
$animal -> drive();//This is Dog drive!
$animal::say();//调用静态方法,This is dog say!
$animal -> test();//1
$animal -> test();//2
?>

匿名类

PHP 7 开始支持匿名类。 匿名类很有用,可以创建一次性的简单对象。 可以传递参数到匿名类的构造器,也可以 扩展(extend)其他类、实现接口(implement interface),以及像其他普通的类一样使用 trait
class  SomeClass  {}
interface 
SomeInterface  {}
trait 
SomeTrait  {}
//使用new class来创建匿名类
var_dump (new class( 10 ) extends  SomeClass  implements  SomeInterface  {
    private 
$num ;
    public function 
__construct ( $num )
    {
        
$this -> num  $num ;
    }
    use 
SomeTrait
});
匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来:
<?php
header("Content-type: text/html; charset=utf-8");
class Outer{
 private $prop = 1;
 protected $prop2 = 2;
 protected function func1(){
  return 3;
 }
 public function func2(){
  return new class($this ->prop) extends Outer{
   private $prop3;
   public function __construct($prop){
    $this -> prop3 = $prop;
   }
   public function func3(){
    return $this -> prop2 + $this -> prop3 + $this->func1();
   }
  };
 }
}
echo (new Outer) -> func2() -> func3();//6
?>
声明的同一个匿名类,所创建的对象都是这个类的实例。

<?php
function anonymous_class()
{
    return new class {};
}

if (
get_class(anonymous_class()) === get_class(anonymous_class())) {
    echo 
'same class';
} else {
    echo 
'different class';
}

Note:  注意,匿名类的名称是通过引擎赋予的,如下例所示。 由于实现的细节,不应该去依赖这个类名。
<?php
echo  get_class (new class {});

猜你喜欢

转载自blog.csdn.net/mx_studying/article/details/80995166