php面向对象编程(二),php面向对象编程现在我们来了解一下面向对象的一个封装性的问题
封装性:在我的理解里面 可以理解为一个u盘 我们使用u盘的接口与电脑进行数据之间的交互 但是我们不能看到里面的结构 这个特性我们可以称为封装性
好处:利用这个特性我们可以最大程度的提高代码的质量 我们在其他代码中只要对接口进行引用不用每次都写 提高代码的自量 以及减少排除bug的难度
现在我们来思考个问题:个人电脑都有一个密码,不想让其它人随意的登陆,在你电脑里面拷贝和粘贴。还有就是像人这个对象, 身高和年龄的属性, 只能是自己来增涨,不可以让别人随意的赋值等等。
我们使用private这个关键词对代码进行封装
private $name; // 把人的姓名使用private关键字进行封装private $sex; // 把人的性别使用private关键字进行封装private $age; // 把人的年龄使用private关键字进行封装private function run(){……} // 把人的走路方法使用private关键字进行封装
注意:只要成员属性前面有其他的关键字,那么就要去掉var
name . 性别: . $this->sex . 我的年龄是: . $this->age; } // 这个人可以走路的方法, 被private封装上了 private function run() { echo 这个人在走路; }}// 实例化一个人的实例对象$p1 = new person();// 试图去给私有的属性赋值, 结果会发生错误$p1->name = 张三;$p1->sex = 男;$p1->age = 20;// 试图去打印私有的属性, 结果会发生错误echo $p1->name;echo $p1->sex;echo $p1->age;// 试图去打印私有的成员方法, 结果会发生错误$p1->run();?>
输出结果为:
fatal error: cannot access private property person::$name
fatal error: cannot access private property person::$sex
fatal error: cannot access private property person::$age
fatal error: cannot access private property person::$name
fatal error: call to private method person::run() from context ' '
没有加任何访问控制,默认的是public的,任何地方都可以访问。
// 这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法function say(){ echo 我的名子叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age; // 在这里也可以访问私有方法 //$this->run();}
因为成员方法say()是公有的, 所以我们在类的外部调用say()方法是可以的,改变上面的代码:
name赋初使值 $this->name = $name; // 通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值 $this->sex = $sex; // 通过构造方法传进来的$age给私有成员属性$this->age赋初使值 $this->age = $age; } // 这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法 function say() { echo 我的名子叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age; }}// 通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄$p1 = new person(张三, 男, 20);$p2 = new person(李四, 女, 30);$p3 = new person(王五, 男, 40);// 下面访问$p1对象中的说话方法$p1->say();// 下面访问$p2对象中的说话方法$p2->say();// 下面访问$p3对象中的说话方法$p3->say();?>
因为构造方法是默认的公有方法(构造方法不要设置成私有的),如果设置称为私有的话,就等同将u盘中的唯一一个接口封死,我们就不能对这个类进行访问
上面的例子中我们可以看到, 私有的成员只能在类的内部使用, 不能被类外部直接来存取 但是我们有时候有需要对私有属性进行赋值和读取,我们需要给类的外部提供一些可以存取的接口。
prvate $age; // 私有的属性年龄function setage($age) // 为外部提供一个公有设置年龄的方法 { if ($age130) // 在给属性赋值的时候,为了避免非法值设置给属性 return; $this->age = $age;}function getage() // 为外部提供一个公有获取年龄的方法 { return($this->age);}
下面我们要了解一下__set,__get,__isset,__unset四个方法的应用
经过上面的讲解可能会有疑问 那么我们如何对私有类进行操作呢?????
__set设置:__get
$property_name)) { return ($this->$property_name); } else { return (null); }}//__set()方法用来设置私有属性function __set($property_name, $value){ $this->$property_name = $value;}
一个完整的示例:
$property_name)) { return ($this->$property_name); } else { return null; } } //__set()方法用来设置私有属性 function __set($property_name, $value) { echo 在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
; $this->$property_name = $value; }}$p1 = new person();// 直接为私有属性赋值的操作, 会自动调用__set()方法进行赋值$p1->name = 张三;$p1->sex = 男;$p1->age = 20;// 直接获取私有属性的值, 会自动调用__get()方法,返回成员属性的值echo 姓名: . $p1->name .
;echo 性别: . $p1->sex .
;echo 年龄: . $p1->age .
;?>
程序执行结果:
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接获取私有属性值的时候,自动调用了这个__get()方法
姓名:张三
在直接获取私有属性值的时候,自动调用了这个__get()方法
性别:男
在直接获取私有属性值的时候,自动调用了这个__get()方法
年龄:20
以上代码如果不加上__get()和__set()方法,程序就会出错,因为不能在类的外部操作私有成员,而上面的代码是通过自动调用__get()和__set()方法来帮助我们直接存取封装的私有成员的。
如果在一个对象外面使用“isset()”这个函数去测定对象里面的成员是否被设定可不可以用它呢?分两种情况,如果对象里面成员是公有的,我们就可以使用这个函数来测定成员属性,如果是私有的成员属性,这个函数就不起作用了,原因就是因为私有的被封装了,在外部不可见。那么我们就不可以在对象的外部使用“isset()”函数来测定私有成员属性是否被设定了呢?可以,你只要在类里面加上一个“__isset()”方法就可以了,当在类外部使用”isset()”函数来测定对象里面的私有成员是否被设定时,就会自动调用类里面的“__isset()”方法了帮我们完成这样的操作,“__isset()”方法也可以做成私有的。你可以在类里面加上下面这样的代码就可以了:
private function __isset($nm){ echo 当在类外部使用isset()函数测定私有成员$nm时,自动调用
; return isset($this->$nm);}
完整例子
$property_name)) { return ($this->$property_name); } else { return null; } } // __set()方法用来设置私有属性 private function __set($property_name, $value) { $this->$property_name = $value; } // __isset()方法 private function __isset($nm) { echo isset()函数测定私有成员时,自动调用
; return isset($this->$nm); } //__unset()方法 private function __unset($nm) { echo 当在类外部使用unset()函数来删除私有成员时自动调用的
; unset($this->$nm); }}$p1 = new person();$p1->name = this is a person name;// 在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为trueecho var_dump(isset($p1->name)) . ;echo $p1->name .
;// 在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性unset($p1->name);// 已经被删除了,所这行不会有输出echo $p1->name;?>
输出结果为:
isset()函数测定私有成员时,自动调用
boolean true
this is a person name
当在类外部使用unset()函数来删除私有成员时自动调用的
isset()函数测定私有成员时,自动调用
下面我们要来了解的是继承的知识
下面是人类的代码
// 定义一个“人”类做为父类class person{ // 下面是人的成员属性 var $name; //人的名子 var $sex; //人的性别 var $age; //人的年龄 // 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name, $sex, $age) { $this->name = $name; $this->sex = $sex; $this->age = $age; } // 这个人可以说话的方法, 说出自己的属性 function say() { echo 我的名子叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age; }}
下面是学生类的代码
class student{ // 下面是人的成员属性 var $name; // 人的名字 var $sex; // 人的性别 var $age; // 人的年龄 var $school; // 学生所在学校的属性 // 定义一个构造方法参数为属性姓名$name、性别$sex 和年龄$age 进行赋值 function __construct($name = , $sex = , $age = , $school = ) { $this->name = $name; $this->sex = $sex; $this->age = $age; $this->school = $school; } // 这个人可以说话的方法, 说出自己的属性 function say() { echo 我的名字叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age .
; } // 这个学生学习的方法 function study() { echo 我的名字叫: . $this->name . 我正在 . $this->school . 学习
; }}
对学生类进行简化
class student extends person{ var $school; // 学生所在学校的属性 // 这个学生学习的方法 function study() { echo 我的名字叫: . $this->name . 我正在 . $this->school . 学习
; }}
现在我们要考虑的是重载的问题
这个时候你可能会有疑问 php 好像是不能重载的,因为php是一门若语言的,传统意义上的重载是有多个的方法名相同的方法,但是带有不同个数的参,我们利用参数的不同调用不同的接口
我所说的重载是子类对父类的一个覆盖
name = $name; $this->sex = $sex; $this->age = $age; } // 这个人可以说话的方法, 说出自己的属性 function say() { echo 我的名子叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age; }}class student extends person{ var $school; // 学生所在学校的属性 // 这个学生学习的方法 function study() { echo 我的名子叫: . $this->name . 我正在 . $this->school . 学习; } // 这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法 function say() { echo 我的名子叫: . $this->name . 性别: . $this->sex . 我的年龄是: . $this->age . 我在 . $this->school . 上学; }}?>
这样就能实现了 这种方法归根到底是的要点是:
1。子类要对父类继承
2.子类的方法名要与父类的方法名相同
这个时候我们可能发现如果这个方法中有1000条代码那么 实现起来很不方便
此时我们,使用“parent::方法名”的方试来调用父类中被覆盖的方法;
class student extends person{ var $school; // 学生所在学校的属性 // 这个学生学习的方法 function study() { echo 我的名子叫: . $this->name . 我正在 . $this->school . 学习; } // 这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法 function say() { // 使用父类的类名::来调用父类中被覆盖的方法; // person::say(); // 或者使用parent::的方试来调用父类中被覆盖的方法; parent::say(); // 加上一点自己的功能 echo 我的年龄是: . $this->age . 我在 . $this->school . 上学; }}
对public,private,protected的区别
mypublic(); $this->myprotected(); $this->myprivate(); }}$myclass = new myclass;$myclass->mypublic(); // works$myclass->myprotected(); // fatal error$myclass->myprivate(); // fatal error$myclass->foo(); // public, protected and private work/** * define myclass2 */class myclass2 extends myclass{ // this is public function foo2() { $this->mypublic(); $this->myprotected(); $this->myprivate(); // fatal error }}$myclass2 = new myclass2;$myclass2->mypublic(); // works$myclass2->foo2(); // public and protected work, not private?>
从上面的代码我们可以总结如下
public:可以直接进行外部访问
protected 间接的外部访问 像u盘和电脑一样 访问需要一个接口 而那个接口就是需要一个子类 (子类继承了父类的protected)
private 不能通过外部访问
既然谈到继承的问题 如果我们想要一个类不被继承那么我们可以用final 去进行定义(只能定义类和方法,不能定义成员属性)
1.final 标记的类不能被继承
2.final标记的方法不能被子类覆盖
会出现下面错误:
fatal error: class student may not inherit from final class (person)
理解static 和const的关键关键字的使用(self:)
static 字面上的意思就是静态的意思 现在你可能会问静态使用静态有什么好处?使用静态的好处是:如果示例话成千上万“人”的对象,里面都有一个共有的属性比如国籍“中国”,那么我们可以建国籍这个属性设置为静态,在内存在开辟出一个位置,实例化的过程中成千上万的人都会访问内存中这个位置
static成员能够限制外部的访问,因为static的成员是属于类的,是不属于任何对象实例,是在类第一次被加载的时候分配的空间,其他类是无法访问的,只对类的实例共享,能一定程度对类该成员形成保护;
这一点有点像网站中的全局变量
结果是:
中国我是中国人美国
也可以这么写
showconstant();// echo $class::constant; // 是不允许的?>
用“const”修饰的成员属性的访问方式和“static”修饰的成员访问的方式差不多,也是使用“类名”,在方法里面使用“self”关键字。但是不用使用“$”符号,也不能使用对象来访问。
showconstant();// echo $class::constant; // 是不允许的?>
http://www.bkjia.com/phpjc/1101501.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/1101501.htmltecharticlephp面向对象编程(二),php面向对象编程 现在我们来了解一下面向对象的一个封装性的问题 封装性:在我的理解里面 可以理解为一个u盘 我们...