- 2019-11-17
PHP基础加强系列七之OOP相关内容(二...
序言:本篇文章主要讲了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(parameter)
{
if(method == 'getVal') { if(2 == count(parameter))
{
if(is_numeric(parameter[0])&&is_numeric(parameter[1]))
{
return 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(parameter)
{
if(method == 'getVal') { if(2 == count(parameter))
{
if(is_numeric(parameter[0])&&is_numeric(parameter[1]))
{
return 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(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(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(bone);
master->feed(cat,master->feed(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(cat);
Catchable fatal error: Argument 1 passed to Master::feed() must be an instance of Animal, instance of Fish given, called in F:
转载请注明出处,谢谢!
- 上一篇: PHP基础加强系列六之OOP相关内容(一)
- 下一篇: PHP基础加强系列八之OOP相关内容(三)
评论一下