利用java来引入多态
买一个手电筒(说明书上写的手电筒只能装红玻璃),和几个不同颜色的玻璃片,目的是装上不同的玻璃片,显示不同的颜色
public class PolyTest
{
public static void main(String[] args)
{
Light light = new Light();
RedGlass rg = new RedGlass();
BlueGlass bg = new BlueGlass();
light.ons(rg);
light.ons(bg); // I want to show blue light;
}
}
class Light //手电筒
{
public void ons(RedGlass red) //对应了说明书上写的只能装红玻璃
{
red.display();
}
}
class RedGlass //红玻璃
{
public void display()
{
System.out.println("red light");
}
}
class BlueGlass //蓝玻璃
{
public void display()
{
System.out.println("BlueGlass");
}
}
/**
这样一段代码,在java中 编译通不过.
原因是:
public void ons(RedGlass red)
{
red.display();
}
ons方法, 指定了 接收的参数必须是 RedGlass,即红玻璃对象
因此,你传一个蓝光玻璃,不行!
强类型语言的一个特点,
函数参数,函数的返回值,都是定死的.
改进上述java代码
让手电筒安装什么玻璃片就显示什么颜色
只需要让RedGlass和BlueGlass都继承一个父类Glass,说明书上声明安装玻璃Glass,不说明安装什么颜色的玻璃
上面程序的php实现
class Light {
// 开灯, 传一个玻璃参数
public function ons($g) {
$g->display(); // 用玻璃渲染颜色
}
}
class RedGlass {
public function display() {
echo '红光照耀<br />';
}
}
class BlueGlass {
public function display() {
echo '蓝光照耀<br />';
}
}
class GreenGlass {
public function display() {
echo '绿光照耀<br />';
}
}
class Pig {
public function display() {
echo '八戒下凡,哼哼坠地!<br />';
}
}
// 创建一个手电筒
$light = new Light();
// 创建3块玻璃
$red = new RedGlass();
$blue = new BlueGlass();
$green = new GreenGlass();
// 变红灯
$light->ons($red);
// 为蓝灯
$light->ons($blue);
// 变绿灯
$light->ons($green);
// 调用错了
$pig = new Pig();
$light->ons($pig); //任然何以运行
分析 与java那段出错程序相比
php没报错,
因为PHP是弱类型动态语言.
一个变量
$var = 8;
$var = 'hello';
$var = new Pig();
一个变量,没有类型,你装什么变量都行.
同理,传参,参数也没有强制类型.
传什么参都行.
所以,对于PHP动态语言来说,岂止是多态,简直是变态.
又有专家说, 你这个太灵活了,简直变态,不能这么灵活.
否则我们就不说你多态.
答:别急,我们不让php这么灵活还不行吗
我对参数做类型限制总行了吧.
见下一页
变态是因为没有限制类型,现在我们对参数做类型限制
限制类型的php
class Light {
// 此处,仿java,也加一个类名,做参数类型检测
public function ons(RedGlass $g) {
// 用玻璃渲染颜色
$g->display();
}
}
class RedGlass {
public function display() {
echo '红光照耀<br />';
}
}
class BlueGlass {
public function display() {
echo '蓝光照耀<br />';
}
}
class GreenGlass {
public function display() {
echo '绿光照耀<br />';
}
}
class Pig {
public function display() {
echo '八戒下凡,哼哼坠地!<br />';
}
}
$light = new Light();// 造手电筒
$red = new RedGlass();// 造红玻璃
$blue = new BlueGlass();// 造蓝玻璃
$light->ons($red);// 红灯亮
$light->ons($blue);// 出错:atchable fatal error: Argument 1 passed to Light::ons() must be an instance of RedGlass, instance of BlueGlass given
说明:
加了类型检测后,果然传蓝玻璃不行.
哲学: 子类是父类, 例:男人是人,白马是马,蓝玻璃是玻璃.
里氏代换: 原能用父类的场合,都可以用子类来代替.
解决:参数定为父类,传其子类.
php实现
class Light {
// 此处,仿java,也加一个类名,做参数类型检测
public function ons(RedGlass $g) { //只能检测对象,这里即使传入int,也是按照对象看待
// 用玻璃渲染颜色
$g->display();
}
}
class Glass{
public function display(){}
}
class RedGlass extends Glass{
public function display() {
echo '红光照耀<br />';
}
}
class BlueGlass extends Glass {
public function display() {
echo '蓝光照耀<br />';
}
}
class Pig {
public function display() {
echo '八戒下凡,哼哼坠地!<br />';
}
}
$light = new Light();// 造手电筒
$red = new RedGlass();// 造红玻璃
$blue = new BlueGlass();// 造蓝玻璃
$light->ons($red);// 红灯亮 成功
$light->ons($blue);//蓝灯亮 成功
// 猪八戒降生
$pig = new Pig();
$light->ons($pig); //出错,要的是Glass对象,传入的却是pig对象
说明;
如果按PHP本身特点,不检测类型,本身就可以说是多态的,甚至变态的.
但是PHP5.3以后,引入了对于对象类型的参数检测,
注意 只能检测对象所属的类
其实,这对于PHP来说,限制了其灵活性,达到的java中多态的效果.
反思多态:
其实就是
只抽象的声明父类, 具体的工作由子类对象来完成
这样,不同的子类对象完成,有不同的特点