随笔 - 72,  文章 - 0,  评论 - 1,  阅读 - 22557

在 PHP 中,类的继承(继承)是一种机制,允许一个类继承另一个类的属性和方法,从而实现代码的重用和扩展。继承可以帮助你创建一个基于现有类的新类,保留原有类的特性并增加或修改其功能。

复制代码
    class Animal {

        public $name='dongwu';
        protected $age=1;
        private $birth='2024';
   }  
    
    class Cat extends Animal{}    //使用extends 关键字继承父类 注意花括号后面没有分号
    
    var_dump(new Animal);
    var_dump(new Cat);
复制代码

var_dump 2个类看看内容,除了名字不同,内容都是一样的。

[Running] D:\ceshi.test\3.php"
object(Animal)#1 (3) {
  ["name"]=>
  string(6) "dongwu"
  ["age":protected]=>
  int(1)
  ["birth":"Animal":private]=>
  string(4) "2024"
}
object(Cat)#1 (3) {
  ["name"]=>
  string(6) "dongwu"
  ["age":protected]=>
  int(1)
  ["birth":"Animal":private]=>
  string(4) "2024"
}
 
接下来尝试调用Animal类的变量
复制代码
    class Animal {

        public $name='dongwu';
        protected $age=1;
        private $birth='2024';
   }  
    
    class Cat extends Animal{}
    
    $obj = new Cat;
    echo $obj->name;   //只有这个public 的name可以被打印
    echo $obj->age;    //虽然是子类可以拿到,但是是在类的内部可以拿到,外部想要拿到的话,需要使用函数的方式拿到
    echo $obj->birth;  //私有类型的,子类无法拿到
复制代码

接下来演示如何拿到protected的age

复制代码
 class Animal {

        public $name='dongwu';
        protected $age=1;
        private $birth='2024';
   }  
    
    class Cat extends Animal{

        function getage(){    //使用方法拿到age,由此可见protected类型的变量只能在类的内部拿到
            
            echo $this->age;
        }

    }

    
    $obj = new Cat;
   
    echo $obj->getage();
复制代码

回显如下:

[Running] D:\ceshi.test\3.php"
1
 
接下来再看下面的这段代码
复制代码
    class Animal {

        protected $name;

        public function __construct($name){

            $this->name =$name;        //通过构造函数赋值给类里面的name变量
        }

        public function eat(){

            echo $this->name. ' is eatting';
        }
   }  

   class Cat extends Animal{
       
        public function meow(){      //子类自有的方法

            echo $this->name.'is meowing';
        }
   }

   $cat = new Cat('lanmao');

   var_dump($cat);
   $cat->eat();
   $cat->meow();
复制代码

回显如下:

[Running] D:\ceshi.test\3.php"
object(Cat)#1 (1) {
  ["name":protected]=>
  string(6) "lanmao"
}
lanmao is eattinglanmaois meowing
由此可见 vardump只能打印出父类的变量(属性),而不能打印出方法。实际是可以继承过来的,只是无法通过vardump打印出来。比如父类的构造方法和其他方法都被继承了过来。
 
类方法和属性(变量)的重写
如果从父类继承的方法或属性不能满足子类的需求,可以对其进行改写,下面的这段代码中父类虽然有了eat方法,但是子类在继承后又重写了eat方法,所以会执行子类的eat方法而忽略父类的eat方法
复制代码
  class Animal {

        protected $name;

        public function __construct($name){

            $this->name =$name;
        }

        public function eat(){

            echo $this->name. ' is eatting';  //虽然父类中有了eat方法
        }
   }  

   class Cat extends Animal{
       
        public function eat(){

        echo $this->name. ' is eatting2';  //子类重写了eat方法后,会忽略父类中的eat方法

        }

        public function meow(){

            echo $this->name.'is meowing';
        }
   }

   $cat = new Cat('lanmao');
$cat->eat();
复制代码

回显如下:

[Running] D:\ceshi.test\3.php"
lanmao is eatting2
同样,属性(变量)也可以重写,看下面的例子
复制代码
 class Animal {

        protected $name='fish';    //初始值设置为fish

        public function eat(){

            echo $this->name. ' is eatting';
        }
   }  

   class Cat extends Animal{
       
        protected $name='fox';   //子类中重写属性

        public function meow(){

            echo $this->name.' is meowing';
        }
   }

   $cat = new Cat();

   $cat->meow();
   
复制代码

回显如下:

[Running] D:\ceshi.test\3.php"
foxis meowing
 
 final 关键字
作用:
防止类被集成  
防止类的方法被重写
 
先看阻止类方法重写
复制代码
class Animal {

        protected $name;

        public function __construct($name){

            $this->name =$name;
        }

   final public function eat(){    //类方法前加上final,则这个类无法被继承

            echo $this->name. ' is eatting';
        }
   }  

   class Cat extends Animal{
       
        public function eat(){

        echo $this->name. ' is eatting2';

        }

        public function meow(){

            echo $this->name.'is meowing';
        }
   }

   $cat = new Cat('lanmao');$cat->eat();
复制代码

回显如下:

[Running] D:\ceshi.test\3.php
PHP Fatal error:  Cannot override final method Animal::eat() in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
Fatal error: Cannot override final method Animal::eat() in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
 
再看阻止类继承
复制代码
  final class Animal {      //此处加上final来阻止类被继承

        protected $name;

        public function __construct($name){

            $this->name =$name;
        }

    public function eat(){

            echo $this->name. ' is eatting';
        }
   }  

   class Cat extends Animal{
       
        public function eat(){

        echo $this->name. ' is eatting2';

        }

        public function meow(){

            echo $this->name.'is meowing';
        }
   }

   $cat = new Cat('lanmao');$cat->eat();
复制代码

回显如下:

[Running] D:\ceshi.test\3.php"
PHP Fatal error:  Class Cat may not inherit from final class (Animal) in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
Fatal error: Class Cat may not inherit from final class (Animal) in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
 
 在 PHP 中,可以通过 parent:: 关键字在子类中调用父类的方法。例如:
复制代码
class ParentClass {
    public function greet() {
        echo "Hello from ParentClass!";
    }
}

class ChildClass extends ParentClass {
    public function greet() {
        // 调用父类的 greet() 方法
        parent::greet();
        echo " And hello from ChildClass!";
    }
}

$child = new ChildClass();
$child->greet();
复制代码

回显如下:

[Running] D:\ceshi.test\6.php"
Hello from ParentClass! And hello from ChildClass!
 
继续看调用父类的构造函数
复制代码
class ParentClass {
    public function __construct($name) {
        echo "ParentClass constructor with name: $name";   //父类的构造函数有一个name传进来
    }
}

class ChildClass extends ParentClass {
    public function __construct($name, $age) {
        // 调用父类的构造函数
        parent::__construct($name);
        echo "ChildClass constructor with age: $age";  //不仅能输出自己的构造函数,还能输出父类的构造函数
    }
}

$child = new ChildClass('Alice', 25);
复制代码

回显如下:

[Running] D:\ceshi.test\6.php"
ParentClass constructor with name: Alice
ChildClass constructor with age: 25
 
同样,也可以重写父类继承过来的构造函数
 
复制代码
class ParentClass {
    public function __construct($name) {
        echo "ParentClass constructor with name: $name";
    }
}

class ChildClass extends ParentClass {
    public function __construct($age) {
        // 直接重写继承自父类的构造函数,需要注意的是父类的构造函数本身不会受到影响
        echo "ChildClass constructor with age: $age";
    }
}
复制代码

回显如下:

[Running] D:\ceshi.test\6.php"
ChildClass constructor with age: 25
 
静态延迟绑定static 
是指在运行时根据实际调用的类来确定静态方法或属性的绑定
static::$name
来看下面这段代码
在这个示例中,self::$namestatic::$name 的行为是不同的。self::$name 在任何情况下都指向 Animal 类的 $name 属性,而 static::$name 使用的是静态延迟绑定,这意味着它会指向当前调用 eat() 方法的类的 $name 属性。由于你是通过 Animal::eat() 调用的,结果如下:
复制代码
<?php

class Animal {

    protected static $name = 'Animal';

    public static function eat() {
        echo self::$name . ' is eating';
        echo '----';
        echo static::$name . ' is eating';
    }

}

Animal::eat();

?>
复制代码
[Running] D:\ceshi.test\6.php"
Animal is eating----Animal is eating
如果你有子类 Dog 继承自 Animal,并重写 $name 属性,调用 Dog::eat() 将会展示不同的结果:
复制代码
<?php

class Animal {

    protected static $name = 'Animal';

    public static function eat() {
        echo self::$name . ' is eating';
        echo '----';
        echo static::$name . ' is eating';
    }

}

class Dog extends Animal {
    protected static $name = 'Dog';
}

Dog::eat();

?>
复制代码
[Running] D:\phpstudy_pro\Extensions\php\php7.3.4nts\php.exe "d:\phpstudy_pro\WWW\ceshi.test\6.php"
Animal is eating----Dog is eating
此时static::$name 使用静态延迟绑定,指向实际调用方法的类 Dog 中的 $name 属性。由于 Dog 类覆盖了 Animal 类的 $name 属性,所以 static::$name 输出的是 Dog.这就是静态绑定
 
posted on   wilson'blog  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示