面向对象:多态,静态方法

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
private
protected
public
三者的区别


private protected public
本类内 Y Y Y
子类内 N Y Y
外部 N N Y


注意:
在java中,如果属性/方法前面不写任何参数
即public/protected/private都不写,也是可以的,friendly

在PHP中,如果public/protected/private 都不写,
则理解为 public 建议养成好习惯,不要不写

 

***/


/****
代码部分
****/


class Human {
private $name = 'zhangsan';
protected $money = 3000;
public $age = 28;

public function say() {
echo '我叫',$this->name,'<br />';
echo '我有',$this->money,'元钱<br />';
echo '我今年',$this->age,'岁';
}
}

 

class Stu extends Human {
private $friend = '小花';

public function talk() {
echo '我叫',$this->name,'<br />';
echo '我有',$this->money,'元钱<br />';
echo '我今年',$this->age,'岁<br />';
}
}


$ming = new Stu();
echo $ming->age,'<br />'; // 28

// 下行错,因为类外不能调用private
// echo $ming->friend;

// 下行错,因为类外不能调用protected属性
// echo $ming->money;

/*
总结:
public 可以在类外调用,权限最为宽松
protected和 private不能在类外调用

?? public 在类内调用行不行
答:当然行,类外都可以,权限很宽松,类内自然没问题.
*/


/*
下一行执行时
Notice: Undefined property: Stu::$name in D:\www\1109\02.php on line 44
我有3000元钱
我今年28岁

分析原因: Undefined property: Stu::$name 这是说明:stu对象 没有name属性
但昨天说,私有的不是可以继承吗?
是可以继承过来,但系统有标记,标记其为父类层面的私有属性.
因此无权调用,导致此错发生.


可以分析出:
protected 可以在 子类内访问

?? protected能在子类访问,本类内能否访问?
答:当然可以
*/
$ming->talk();

 

echo '<hr />';

$yuanmou = new Human();
$yuanmou->say();

 

 

 

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====

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,即红玻璃对象
因此,你传一个蓝光玻璃,不行!


强类型语言的一个特点,
函数参数,函数的返回值,都是定死的.

***/


/****
代码部分
****/

 

 

 

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
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
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====

***/


/****
代码部分
****/

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);

/**

Catchable fatal error: Argument 1 passed to Light::ons() must be an instance of RedGlass, instance of BlueGlass given, called in D:\www\1109\05.php on line 72 and defined in D:\www\1109\05.php on line 24


加了类型检测后,果然传蓝玻璃不行.

解决:参数定为父类,传其子类.

哲学: 子类是父类, 例:男人是人,白马是马,蓝玻璃是玻璃.

里氏代换: 原能用父类的场合,都可以用子类来代替.


见下一页的解决
**/

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/

 

class Light {

// 此处,仿java,也加一个类名,做参数类型检测
public function ons(int $g) {
// 用玻璃渲染颜色
$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 GreenGlass 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);


/****
如果按PHP本身特点,不检测类型,
本身就可以说是多态的,甚至变态的.

但是PHP5.3以后,引入了对于对象类型的参数检测,
注意 只能检测对象所属的类

其实,这对于PHP来说,限制了其灵活性,达到的java中多态的效果.

 

反思多态:
其实就是
只抽象的声明父类, 具体的工作由子类对象来完成
这样,不同的子类对象完成,有不同的特点.
****/

 

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
静态属性 静态方法

在属性,和方法前 加 static 修饰,这种称为静态属性/ 静态方法

***/


class Human {
static public $head = 1;

public function changeHead() {
Human::$head = 9;
}

public function getHead() {
return Human::$head;
}
}


// 现在没有对象,想访问静态的$head属性


/*
普通属性包在对象内,用对象->属性名 来访问
静态属性放在类内的,


静态属性既然存放于类空间内
1:类声明完毕,该属性就已存在,不需要依赖于对象而访问
2:类在内存中只有一个,因此静态属性也只有一个
*/

// 当一个对象都没有,静态属性也已随类声明而存在
echo Human::$head,'<br />'; // 1


// 静态属性只有一个,为所有的对象的共享.
$m1 = new Human();
$m1->changeHead(); // 某个人改变了人类的头的数量


$m2 = new Human();
$m3 = new Human();


echo $m2->getHead(),'<br />'; // 9
echo $m3->getHead(),'<br />'; // 9

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
静态方法

static public/protected/private function t() {
}


普通方法,存放于类内的,只有1份
静态方法,也是存放于类内的,只有1份


区别在于: 普通方法需要对象去调动, 需要绑定$this
即,普通方法,必须要有对象,用对象调动


而静态方法, 不属性哪个对象,属于类,因此不需要去绑定$this,
即, 静态方法,通过类名就可以调动
***/

 

class Human {
public $name = '张三';

static public function cry() {
echo '5555';
}

public function eat() {
echo '吃饭';
}

public function intro() {
echo $this->name;
}
}


// 此时一个对象都没有
Human::cry();

 

/*
下面这个eat方法是一个非静态方法,应由对象来调用
但是呢,调用了,也没出问题
*/
Human::eat();

/*
接上,但从逻辑来理解, 如果用类名静态调用非静态方法
比如 intro()
那么: $this 到底是指哪个对象???

因此,直接报错
Fatal error: Using $this when not in object context in D:\www\1109\08.php on line 45
*/

// Human::intro();

 


/*
如上分析,其实非静态方法,是不能由类名静态调用的.
但是! PHP中的面向对象检测的并不严格,
只要该方法没有$this,就会转化静态方法来调用.
因此,cry()可以调用.


但是,在PHP5.3的strict级别下,或者PHP5.4的默认级别
都已经对类名::非静态方法做了提示


则会提示:Strict Standards: Non-static method Human::eat() should not be called statically
不能静态的去调用非静态方法
*/


Error_reporting(E_ALL|E_STRICT);

Human::eat();

/***
因此此原因导致的典型问题,欢迎解答
http://www.zixue.it/forum.php?mod=viewthread&tid=3756&extra=page%3D1
***/

 

// 动访问静
$lisi = new Human();
$lisi->cry(); // 5555


/*
类->访问->静态方法 可以
类->动态方法 方法内没有this的情况下,但严重不支持.逻辑上解释不通.

对象-->访问动态方法 可以
对象-->静态方法 可以
*/

 

 

 

多态,
静态方法
单例模式


=====昨天回顾===
继承

subClass extends parentClass {
}

继承的特点:
对于protected/public类型的属性/方法
完成继承过来,有权重写,调用.

继承过来的属性/方法:
父类有的,子类也有
父类有的,子类可以改写
父类没有的,子类可以添加


对于pricate类型的属性/方法,比较特殊.
可以继承过来,但有个标记,标记记从属父类而来.
即 在子类内是无权调用继承过来的私有属性/方法的.


构造方法的继承
构造方法也是可以继承的,
new 子类时,如果构造方法继承过来,当然也要自动执行.
但继承过来,子类重写了,自然执行子类的构造方法
(注意,父类的构造方法不再调用)

posted on 2012-11-12 14:34  besile  阅读(290)  评论(0)    收藏  举报