PHP面向对象编程(imooc)代码合集(四)
class10 多态
多态简单说就是用不同的类去实现同一个接口的方法,以实现不同类自己的方法
<?php date_default_timezone_set("PRC"); /** * 多态 * 1. 只要某个对象实现了接口(instanceof),就可以直接在对象上调用接口的方法 */ interface ICanEat { public function eat($food); } // Human类实现了ICanEat接口 class Human implements ICanEat { // 跟Animal类的实现是不同的 public function eat($food){ echo "Human eating " . $food . "\n"; } } // Animal类实现了ICanEat接口 class Animal implements ICanEat { public function eat($food){ echo "Animal eating " . $food . "\n"; } } function eat($obj){ if($obj instanceof ICanEat){ $obj->eat("FOOD"); // 不需要知道到底是Human还是Animal,直接吃就行了 }else{ echo "Can't eat!\n"; } } $man = new Human(); $monkey = new Animal(); // 同样的代码,传入接口的不同实现类的时候,表现不同。这就是为什么成为多态的原因。 eat($man); eat($monkey); ?>
class11 抽象类
抽象类是介于接口和一般类之间的一个类,它允许自身的某些方法暂时没有具体实现;但是,抽象类和接口一样,不能直接实例化为对象,必须要一个一般类去继承它,它只能作为父类被使用
<?php date_default_timezone_set("PRC"); /** * 抽象类 * 1. 抽象类允许类里面的部分方法暂时没有具体实现,这些方法我们成为抽象方法 * 2. 一旦类里面有抽象方法,这个类就必须是抽象类 * 3. 抽象类跟接口一样,不能直接实例化为对象 */ // 抽象类前面以abstract关键字开始 abstract class ACanEat { // 没有实现的方法需要设定为抽象方法 // 抽象方法需要在子类中实现 abstract public function eat($food); public function breath(){ echo "Breath use the air.\n"; } } // Human类实现了ICanEat接口 class Human extends ACanEat { // 跟Animal类的实现是不同的 public function eat($food){ echo "Human eating " . $food . "\n"; } } // Animal类实现了ICanEat接口 class Animal extends ACanEat { public function eat($food){ echo "Animal eating " . $food . "\n"; } } $man = new Human(); $man->eat("Apple"); $man->breath(); // 和Animal共用了抽象类ICanEat的breath方法 $monkey = new Animal(); $monkey->eat("Banana"); $monkey->breath(); ?>
这只后给大家简单介绍一下PHP中特有的一些方法(PHP特性),他们分别是
__tostring()--能使对象当做String直接调用 __invoke() --能使对象被当成方法被自动调用
class12
__tostring()--能使对象当做String直接调用 __invoke() --能使对象被当成方法被自动调用
<?php date_default_timezone_set("PRC"); /** * 魔术方法1 * 1. 当对象被当做String使用时,__tostring()会被自动调用 * 2. 当对象被当成方法调用时,__invoke()会被自动调用 */ class MagicTest{ public function __tostring(){ return "This is the Class MagicTest.\n"; } public function __invoke($x){ echo "__invoke called with parameter " . $x . "\n"; } } $obj = new MagicTest(); echo $obj; $obj(5); //直接在对象中传入参数5,它会被__invoke()函数接收 ?>
class13
1. 当对象访问不存在的方法名称时,__call()方法会被自动调用 2. 当对象访问不存在的静态方法名称时,__callStatic()方法会被自动调用
<?php date_default_timezone_set("PRC"); /** * 魔术方法2之方法重载 * 1. 当对象访问不存在的方法名称时,__call()方法会被自动调用 * 2. 当对象访问不存在的静态方法名称时,__callStatic()方法会被自动调用 */ class MagicTest{ public function __tostring(){ return "This is the Class MagicTest.\n"; } public function __invoke($x){ echo "__invoke called with parameter " . $x . "\n"; } public function __call($name, $arguments){ echo "Calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n"; } public static function __callStatic($name, $arguments){ echo "Static calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n"; } } $obj = new MagicTest(); $obj->runTest("para1", "para2"); MagicTest::runTest("para3","para4"); ?>
class14
__set()
__get()
isset()
empty()
unset()
__unset()
<?php date_default_timezone_set("PRC"); /** * 魔术方法3之属性重载 * 1. 在给不可访问属性赋值时,__set() 会被调用。 * 2. 读取不可访问属性的值时,__get() 会被调用。 * 3. 当对不可访问属性调用 isset() 和empty()时,__isset() 会被调用。 * 4. 当对不可访问属性调用 unset() 时,__unset() 会被调用 */ class MagicTest{ public function __tostring(){ return "This is the Class MagicTest.\n"; } public function __invoke($x){ echo "__invoke called with parameter " . $x . "\n"; } public function __call($name, $arguments){ echo "Calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n"; } public static function __callStatic($name, $arguments){ echo "Static calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n"; } // 通过这两个方法可以实现动态的对象属性 public function __get($name){ return "Getting the property " . $name; } public function __set($name, $value){ echo "Setting the property " . $name . " to value ". $value. "\n"; } public function __isset($name){ echo "__isset invoked\n"; return false; } public function __unset($name){ echo "unsetting property " . $name; } } $obj = new MagicTest(); echo $obj->name . "\n"; $obj->name = "Name Value"; echo '$obj->name is set? '. isset($obj->name) . "\n"; echo '$obj->name is empty?' . empty($obj->name) . "\n"; unset($obj->name); ?>
后边几个魔术方法,具体在什么时候调用呢?
我觉得是用于容错处理的。