当前位置:Gxlcms > PHP教程 > (进阶篇)PHP面向对象三大特点学习(封装、继承、多态)

(进阶篇)PHP面向对象三大特点学习(封装、继承、多态)

时间:2021-07-01 10:21:17 帮助过:6人阅读

以下是文章正文:


一、封装性

封装就是把抽取出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有被授权的操作(方法)才能对数据进行操作。

php提供了三种访问控制修饰符

public 表示全局,本类内部,类外部,子类都可以访问

protected 表示受保护的,只有本类或子类可以访问

private 表示私有的,只有本类内部可以访问

以上三种修饰符既可以修饰方法也可以修饰属性(变量),方法如果没有访问修饰符则默认是public,成员属性必须指定访问修饰符,在PHP4中也有这种写法 var $name,表示公开属性,不推荐这种写法

例:

  1. <?php
  2. class Person{
  3. public $name;
  4. protected $age;
  5. private $salary;
  6. function __construct($name,$age,$salary){
  7. $this->name=$name;
  8. $this->age=$age;
  9. $this->salary=$salary;
  10. }
  11. public function showinfo(){
  12. //这表示三个修饰符都可以在本类内部使用
  13. echo $this->name."||".$this->age."||".$this->salary;
  14. }
  15. }
  16. $p1=new Person('张三',20,3000);
  17. //这里属于类外部,那么如果用下面的方法访问age和salary都会报错
  18. // echo $p1->age; echo$p1->salary;
  19. ?>


那么现在就想在外部访问protected和private的元素和方法该怎么办?

通常做法是通过public函数去访问这些变量 格式:

  1. public function setxxxx($val){
  2. $this->xxxx=$val;
  3. }
  4. public function getxxxx(){
  5. return $this->xxxx;
  6. }

这里带set和get只是为了识别方便,并非必要

如:

  1. public function getsalary(){
  2. return $this->salary;
  3. //扩展:这里可以调用一些方法,如判断用户名等,正确才给访问
  4. }

在外部就可以通过 echo $p1->getsalary();

如果要访问 protected和private也可以使用以下方法,但不推荐使用,只要了解即可

__set() 和 __get()

__set()对protected或private属性进行赋值操作

__set($name,$val);

__get()获取 protected 或 private的值

__get($name);

如:

  1. <?php
  2. class testa{
  3. protected $name;
  4. //使用__set()来管理所有属性
  5. public function __set($pro_name,$pro_val){
  6. //上面$pro_name和$pro_val可自定义
  7. //下面$this->pro_name为既定,不可更改
  8. $this->pro_name=$pro_val;
  9. }
  10. //使用__get()来获取所有属性值
  11. public function __get($pro_name){
  12. if(isset($pro_name)){
  13. return $this->pro_name;
  14. } else {
  15. return null;
  16. }
  17. }
  18. }
  19. $n1=new testa();
  20. //正常情况,类外部是不能访问protected属性的,
  21. 但是用了上面的方法就可以对它们进行操作
  22. $n1->name='小三';
  23. echo $n1->name;
  24. ?>


二、继承性

先看一个例子:

  1. <?php
  2. class Pupil{
  3. public $name;
  4. protected $age;
  5. public function getinfo(){
  6. echo $this->name.'||'.$this->age;
  7. }
  8. public function testing(){
  9. echo 'this is pupil';
  10. }
  11. }
  12. class Graduate{
  13. public $name;
  14. protected $age;
  15. public function getinfo(){
  16. echo $this->name.'||'.$this->age;
  17. }
  18. public function testing(){
  19. echo 'this is Graduate';
  20. }
  21. }
  22. ?>

从上面的例子可以看出,当多个类有很多共同属性和方法时,

代码的复用性不高,代码冗余,思考css中的处理方法

解决方法 :继承

  1. <?php
  2. class Students{
  3. public $name;
  4. public $age;
  5. public function __construct($name,$age){
  6. $this->name=$name;
  7. $this->age=$age;
  8. }
  9. public function showinfo(){
  10. echo $this->name.'||'.$this->age;
  11. }
  12. }
  13. class Pupil extends Students{
  14. function testing(){
  15. echo 'Pupil '.$this->name.' is testing';
  16. }
  17. }
  18. class Graduate extends Students{
  19. function testing(){
  20. echo 'Graduate '.$this->name.' is testing';
  21. }
  22. }
  23. $stu1=new Pupil('张三',20);
  24. $stu1->showinfo();
  25. echo '<br/>';
  26. $stu1->testing();
  27. ?>

从上面可以看出,继承就是一个子类(Subclass)通过 extends 父类

把父类(BaseClass)中的public 和 protected 的属性和方法继续下来,

不能继承private属性和方法

语法结构:

  1. class 父类名{}
  2. class 子类名 extends 父类名{}


细节:

1、一个子类只能继承一个父类(这里指直接继承);如果希望继承多个类的属性和方法,

可以使用多层继承

例:

  1. <?php
  2. class A{
  3. public $name='AAA';
  4. }
  5. class B extends A{
  6. public $age=30;
  7. }
  8. class C extends B{}
  9. $p=new C();
  10. echo $p->name;//这里会
输出AAA ?>

2、在创建某个子类对象时,默认情况下不会自动调用其父类的构造函数

例:

  1. class A{
  2. public function __construct(){
  3. echo 'A';
  4. }
  5. }
  6. class B extends A{
  7. public function __construct(){
  8. echo 'B';
  9. }
  10. }
  11. $b=new B();//这里会优先
输出B中的构造方法,

如果B中没有构造方法才会输出A中的

3、在子类中如果需要访问父类的方法(构造方法、成员方法 方法的修饰符为protected或private),

那么可以使用 父类::方法名 或者 parent::方法名 来完成

这里parent和以前提到的self都均为小写,大写报错】

  1. class A{
  2. public function test(){
  3. echo 'a_test';
  4. }
  5. }
  6. class B extends A{
  7. public function __construct(){
  8. //两种方法都行
  9. A::test();
  10. parent::test();
  11. }
  12. }
  13. $b=new B();

5、如果一个子类(派生类)的方法与父类的方法完全一样时(public,protected),

我们称为方法覆盖或方法重写(override),看下面的多态性

三、多态性

例 :

  1. <?php
  2. class Animal{
  3. public $name;
  4. public $price;
  5. function cry(){
  6. echo 'i don\'t know';
  7. }
  8. }
  9. class Dog extends Animal{
  10. //覆盖、重写
  11. function cry(){
  12. echo 'Wang Wang!';
  13. Animal::cry();//这里不会报错,能正确执行父类的cry();
  14. }
  15. }
  16. $dog1=new Dog();
  17. $dog1->cry();
  18. ?>

小结:

1、当一个父类知道所有的子类都有一个方法,但是父类不能确定该方法如何写,可以让子类去覆盖它的方法,方法覆盖(重写),必须要求子类的方法名和参数个数完全一致

2、如果子类要去调用父类的某个方法(protected/public),可以使用 父类名::方法名 或者 parent::方法名

3、在实现方法重写的时候,访问修饰符可以不一样,但是子类方法的访问权限必须大于等于父类方法的访问权限(即不能缩小父类方法的访问权限)

如 父类public function cry(){} 子类 protected function cry(){} 则会报错

但是子类的访问权限可以放大,如:

  1. 父类private function cry(){} 子类 protected function cry(){} 可以正确执行

以上就是(进阶篇)PHP面向对象三大特点学习(封装、继承、多态)的内容,更多相关内容请关注PHP中文网(www.gxlcms.com)!

人气教程排行