PHP基础加强系列七之OOP相关内容(二...

胡三金 2017-06-21 10:17:10 1020 0 comments

序言:本篇文章主要讲了OOP的继承,重载,重写,多态等知识;

(1).继承

1.继承并不是将父类(基类)的代码拷贝到子类,而是建立一种查找关系,当代码运行时,系统会先去子类里面查找是否有可执行的相关代码,如果有则执行,如果没有就去父类找,父类有就执行,父类没有看父类是否还继承其它类,如果有再去其他类找,如果没有则报错;

class Dog{
    public function run()
    {
        echo '狗会跑';
    }
}
class SmallDog extends Dog {
    
}
$smalldog = new SmallDog();
$smalldog->run();

2.php的继承是单继承,一个子类只能同时继承一个父类,不能多继承,其他语言支持;要实现多继承可以由一个子类继承一个父类,而父类再继承其他类,不能说一个类同时继承2个以上的类;

class Dog{
    public function run()
    {
        echo '狗会跑';
    }
}
class BigDog{
    public function talk()
    {
        echo '狗会叫';
    }
}
class SmallDog extends Dog,BigDog {

}
smalldog = new SmallDog(); smalldog->run();

//此时会报错,因为类不能同时继承多个类,可以向下面这样改写

class Dog{
    public function run()
    {
        echo ‘狗会跑’;
    }
}
class BigDog extends Dog {
    public function talk()
    {
        echo ‘狗会叫’;
    }
}
class SmallDog extends BigDog {

}
smalldog = new SmallDog(); smalldog->run();

3.如果子类没有构造函数,子类就去继承父类的构造函数,如果子类有构造函数,就重写父类的构造函数;

class Dog{
    public $name;

    public function __construct(name)     {         this->name = $name;
    }
    public function run()
    {
        echo '狗会跑';
    }
}
class SmallDog extends Dog {

}
smalldog = new SmallDog('小黑'); echo smalldog->name;
//输出小黑

(2).重载(动态的创建方法和属性)

PHP实现重载是通过__call(普通方法),__callStatic(静态方法);普通方法通过魔术方法__call来实现重载;

小例子:

class Person{
    public $name;

    public function __call(method,method,parameter)
    {
        if(method == 'getVal')         {             if(2 == count(parameter))
            {
                if(is_numeric(parameter[0])&&is_numeric(parameter[1]))
                {
                    return parameter[0]+parameter[0]+parameter[1];
                }
            }elseif(count(parameter)>2)             {                 return max(parameter);
            }
        }
    }
}

person = new Person(); echo person->getVal(10,20);
echo ‘’;
echo person->getVal(10,20,30);

//虽然类中并没有定义getVal方法,但是通过__call方法我们动态的创建了方法getVal;而且这种方法很灵活,可以根据实际情况调整;

静态方法通过__callStatic来实现

class Person{
    public name;
    public static function __callStatic(method,method,parameter)
    {
        if(method == 'getVal')         {             if(2 == count(parameter))
            {
                if(is_numeric(parameter[0])&&is_numeric(parameter[1]))
                {
                    return parameter[0]+parameter[0]+parameter[1];
                }
            }elseif(count(parameter)>2)             {                 return max(parameter);
            }
        }
    }
}
person = new Person(); echo person::getVal(10,20);
echo ‘’;
echo person::getVal(10,20,30);

//方法重载是通过__call和__callStatic,属性重载是通过__set()和__get();

(3).重写

当子类继承父类后,假如父类有一个方法叫run(),而子类也有一个方法叫run();这个时候对子类的run()做修改,就叫做方法重写;除此之外,参数的个数也要一致才能叫重写;

1.如果在子类需要访问父类的方法(public\protected),使用父类名::方法名或者parent::方法名;这里访问父类方法不分静态或者普通,都可以访问;

class Person{
    public name = ‘人’;
    public static $age = 100;

    public function run()
    {
        echo '哈哈';
    }

    public static function talk()
    {
        echo ‘哦’;
    }
}
class Human extends Person {
    public function run()
    {
        echo ‘呜呜’;
        parent::run();
        parent::talk();
    }
}
human = new Human(); human->run();

2.parent::静态属性,只能访问父类的静态属性,不能访问普通属性;

class Human extends Person {
    public function run()
    {
        echo ‘呜呜’;
        parent::run();
        parent::talk();
        parent::age;         parent::name;
    }
}

//只能访问父类的静态属性,不能访问普通属性;

3.子类重写不能缩小父类的方法权限;

class Dog{
    public $name;

    public function cry()
    {
        echo ‘哈哈’;
    }
}
class SmallDog extends Dog {
    protected function cry()
    {
        echo ‘haa’;
    }
}
small = new SmallDog(); small->cry();

//父类的cry方法是public的,而子类降低了权限,这样会报错;

 Fatal error: Access level to SmallDog::cry() must be public (as in class Dog)

虽然不能缩小权限,但是可以提高权限;注:这里提高权限前提是父类的方法是protected,如果是private是不行的;因为子类不能访问父类的私有方法;

//提升权限
class Dog{
    public name;     protected function cry()     {         echo '哈哈';     } } class SmallDog extends Dog {     public function cry()     {         echo 'haa';     } } small = new SmallDog();
small->cry();

(4).php类型约束

函数的参数可以指定必须为对象(在函数原型里面指定类的名字),接口,数组(PHP 5.1 起)或者 callable(PHP 5.4 起)。不过如果使用 NULL 作为参数的默认值,那么在调用函数的时候依然可以使用 NULL 作为实参。 如果一个类或接口指定了类型约束,则其所有的子类或实现也都如此。 类型约束不能用于标量类型如 int 或 string。Traits 也不允许。

 小例子:

class Dog{
    public name;
}
function dd(Dog dog,array array,callable function,array arr = null){
    echo ‘
’;
    var_dump(dog,dog,array);
    function(); } dd(new Dog(),[1,2,3],function (){echo '哈哈';},null);

(5).PHP多态

通俗的讲,就是多种状态,在PHP中是指在面向对象中不同情况下的多种状态,根据使用的上下文;php可以根据传入的对象类型的不同,调用对应对象的方法,PHP天生就是多态语言;

小例子:

class Food{
    public name;
    function __construct(name)     {         this->name = name;     } } class Fish extends Food {     public function showName()     {         return this->name;
    }
}
class Bone extends Food{
    public function showName()
    {
        return this->name;     } } class Animal{     public name;
    function __construct(name)     {         this->name = name;     } } class Dog extends Animal{     public function showName()     {         return this->name;
    }
}
class Cat extends Animal{
    public function showName()
    {
        return this->name;     } } class Master{     public name;
    function __construct(name)     {         this->name = $name;
    }

    public function feed(animal,animal,food)
    {
        echo this->name.'的宠物'.animal->showName().'喜欢吃:'.$food->showName().'';
    }
}

dog = new Dog('萨摩耶'); cat = new Cat(‘折耳猫’);
fish = new Fish('鲫鱼'); bone = new Bone(‘排骨’);
master = new Master('小王'); master->feed(dog,dog,bone);
master->feed(cat,fish);fish); master->feed(fish,fish,cat);
输出:
小王的宠物萨摩耶喜欢吃:排骨
小王的宠物折耳猫喜欢吃:鲫鱼
小王的宠物鲫鱼喜欢吃:折耳猫

//这里定义了7个类,一个food类有两个子类fish和bone,一个animal类有两个子类dog和cat,一个master类;在master的feed方法就体现了多态的思想,根据传入的对象类型的不同,调用不同的方法;这里有一个问题,就是没有对参数进行约束,所以会出现鱼吃猫,现在小小的优化一下,将feed的参数进行约束:

public function feed(Animal animal,Food food)
    {
        echo this->name.'的宠物'.animal->showName().‘喜欢吃:’.food->showName().'';     }

//这个时候再来调用鱼吃猫就会报错

master->feed(fish,fish,cat);

Catchable fatal error: Argument 1 passed to Master::feed() must be an instance of Animal, instance of Fish given, called in F:


转载请注明出处,谢谢!




标签
评论一下

评论列表

暂时没有评论,快来评论吧..