面向对象:封装概念 权限修饰符

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

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


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

面向对象三大特征:
封装 继承 多态

封装:

 

***/


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

/*
class Human {
public $money = 1000;
}


$lisi = new Human();
echo $lisi->money,'<br />'; // 1000

// 变一下money
$lisi->money = 500;
echo $lisi->money,'<br />'; // 500
*/
/*
李四的钱,别人问他有多少钱,他就如实说.
别人把他的钱减少,立即减少了.

如果在现实生活中,这个现象显然不合理,
我们需要把钱保护起来

public 是公共的,即大家都可以来读取,操作
钱显然不应该是公共的
*/


class Human {
private $money = 1000;

public function showMoney() {
return $this->money * 0.8;
}
}


$lisi = new Human();

/*
在下例中,调用失败,因为money是私有和,
在外部,不能够被调用
这时,我们就把money "封起来"了

注意:光封起来,是没有意义的,因为money这个属性还得与外界有所交互才行.

*/
// echo $lisi->money,'<br />'; // 1000


// 你不能直接翻别人口袋,看别人有多少钱.
// 但是,可以问别人有多少钱

/*
把某些重要属性 封装起来,然后通过一个开放的接口来操作.
这就实现的对属性的封装.
*/

echo $lisi->showMoney();

 

 

 

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

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


/***
====笔记部分====
继续来看封装,在方法上的体现

***/


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


class Human {
private $money = 1000;
private $bank = 2000;

private function getBank($num) {
$this->bank -= $num;

return $num;
}

public function send($much) {
if($much > $this->money + $this->bank) {
return false;
} else if($much > $this->money){
$num = $much - $this->money; //算算要从银行取多少钱?
$this->money += $this->getBank($num); //从银行取出钱,加到现金里

$this->money -= $much; // 再把钱借给朋友.
return $much;
} else { // 直接现金借
$this->money -= $much;
return $much;
}
}

public function showMoney() {
return $this->money;
}

public function showBank() {
return $this->bank;
}
}

 

$lisi = new Human();

$m = $lisi->send(300);

if($m) {
echo '借了',$m,'元<br />';
echo '还剩下',$lisi->showMoney(),'元<br />';
}


/// 再借 2000 元

$m = $lisi->send(2000);
if($m) {
echo '借了',$m,'元<br />';
echo '还剩下',$lisi->showMoney(),'元<br />';
echo '银行还有',$lisi->showBank(),'元,<br />';
}

/*
在上个例子中,
借钱者,只知道,借成功了,还是借失败了.

至于,如果借成功了,lisi是怎么样把钱凑齐的,
借钱者不会知道lisi也许跑了趟银行,再把钱凑齐.


就像同学们,只需要 每周一到周五,晚8点到10点来听课.
至于后面,老师的备课,拉网线,等等,你们不需要知道.


对于一个对象,对外界开放一个接口,
调用接口时,内部进行的操作,不需要让外界知道.
隐藏了内部的一些实现细节.

这是对方法的封装.


生活中的封装很常见:
电视机,
开电源 一个动作
[隐藏的内部动作: 触发显像管,接线无线电信息,调频 等等]


洗衣机:
扔衣服,通电.
[自动加水,洗,漂,脱水]

*/

 

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

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


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

权限修饰符
作用: 用来说明 属性/方法的权限特点
写在 属性/方法前面

共有3个权限修饰符
private 私有的 , 保护的最严
protected 保护的
public 公共的 ,保护的最松


疑问:
public修饰的属性/方法,可以在哪儿访问?
private 修饰的属性/方法,可以在哪儿访问?


如何判断属性/方法 有没有权限访问?
答:看访问时的位置!

private的属性/方法,只能在类定义的大括号内{},才能访问
public 的属性, 在任意位置都可以访问


***/


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

class Human {
public $mood = ''; // 心情,公有
private $money = 1000; // 钱,私有

public function showMoney() {
return $this->money;
}

private function secret() {
echo '我小时候偷吃过一块肉';
}

public function tellMe() {
$this->secret();
}
}


$lisi = new Human();

$lisi->mood = 'happy';
echo $lisi->mood,'<br />'; // happy;


// echo $lisi->money; // 调用位置在54行,在Human类的{}外面 ,因此,调用失败
// $lisi->money = 500;


echo $lisi->showMoney(),'<br />';
/*
showMoney是公共的,在此行可以调用.
showMoney中的第48号,return $this->money;
这一句运行的环境是在 类的{}内部,因此有权限访问 money属性
*/

// $lisi->secret(); // 不可以
$lisi->tellMe(); // 可以,因为是通过第56行,即,类内调用的.

 

/*
总结: private权限控制

只能在类的{} 内调用,
走出了{}, 谁也调不动.

*/

 

 

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

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


/***
====笔记部分====
看看权限控制的bug
***/


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


class Human {
private $money = 1000;

public function getMoney($people) {
return $people->money;
}

public function setMoney($people) {
$people->money -= 500;
}

}

$zhangsan = new Human();
$lisi = new Human();

// echo $lisi->money; // 不行

// 让李四去打探张三的钱
echo $lisi->getMoney($zhangsan),'<br />';

// 让李四去改变张三的钱
$lisi->setMoney($zhangsan);
echo $lisi->getMoney($zhangsan),'<br />';

print_r($zhangsan);

 

/*
奇怪之处在于,
zhangsan的钱,应该有zhangsan来调用getMoney和setMoney才能影响.

但是和我们前一页面所写的原则是符合的:
即:
41行调用 getMoney,有权.
getMoney() 第26行,又在类的{}内,有权读取私有属性money

44行,调用setMoney,public 有权
setMoney()的第30行,修改zhangsan的money,发生在类的{}内,有权操作

*/

 

 

 

 

 

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

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

 

 

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

class Human {
private $money = 1000;

public function getMoney($people) {
return $people->money;
}

public function setMoney($people) {
$people->money -= 500;
}

}

$zhangsan = new Human();
$lisi = new Human();

// echo $lisi->money; // 不行

// 让李四去打探张三的钱
echo $lisi->getMoney($zhangsan),'<br />';

// 让李四去改变张三的钱
$lisi->setMoney($zhangsan);
echo $lisi->getMoney($zhangsan),'<br />';

/*
李四读取和改变张三的钱,
这如果从生活角度来看,是不合理的

钱私有,是指 "每个对象的钱,针对每个对象私有";
即:张三的钱,由张三->showMoney才能引用.

李四不应该有权直接引用,
或者说,李四->showMoney,也只有权引用 李四自己的money属性.


但是,在上面的代码中,李四却显然引用和改为张三的钱.
这是因为:
PHP在实现上,并不是以对象为单位来控制的权限.
而是以类为单位,来控制的权限,
所以前一页,不断强调 ,类内,类外,而不是说对象内,对象外.


因为 类声明一次,而对象却可能非常多.
以类为单位,简化了判断模型.

 

第三,从代码的来看

zend引擎
ce==EG(scope)
这一句判断的是
调用者属性的类 与 执行上下文所属的类 是否相等


在我们判断中:
$lisi-->类-->Human类
$lisi->setMoney()函数,也在Human类中,
在同一个类内部,可以调用.

这也说明了,确实是以类为单位,以类内类外为界限做的判断


case ZEND_ACC_PRIVATE:
if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope))
{
return 1;
} else {

 

第四 从其他语言来看一看这个问题.
java c#,也存在此问题

 

第五: 从面向对象的角度来考试
我们的写法,也有问题
就不应该把一个对象,直接传给一个方法来使用

而应该 zhangsan borrow钱,
应该对应 lisi sent钱

即 应该尽量的来调用对象的方法,而不应该直接把对象当成参数给传过去.
*/

 

 

 

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