PHP面向对象的小总结
面向对象特性:
*重用性 (每个模块都可以在项目中重复使用)
*灵活性 (每个模块都很轻松被替换更改的)
*拓展性(在模块上添加新功能是很方便的)
类和对象的关系(类生成对象)
物以类聚:相同特性的对象归为一个类,比如nba球员,都有想到的属性姓名,身高体重,球队号码,方法有跑步,跳跃,运球,投篮。将他们当做一个类,而乔丹,詹姆斯这些就是nba球员的实例,也叫对象;
对象内部高内聚(特定的职能,所有相关的内容都封装在对象内部),对外低耦合(对象的一些可见属性和一些可见方法)
用class 声明一个类,在类里面只能有 成员属性 和 成员方法!!!!不能有其他,在一个脚本中不能有两个同名类,实例化类可以有多个对象
class Computer{
public $text = "用关键字new实例化一个类";
public function output(){
echo $this->text;
}
}
$computer = new Computer(); $computer->output();//外部访问方法
$computer->text();//外部访问属性
$computer2 = new Computer();//可以实例化多个
类的属性和方法
访问控制:
public 公有 都可以访问
private 私有 只有类本身内部可以访问
protected 受保护 继承的子类和类本身内部可以访问,外部访问不了,如: $computer->output();如果output()方法设了protected,则报错。
类里面的方法:
方法里面调用一个属性,需要实例化类才能访问属性,而$this可以理解为是这个类的一个实例
class Computer{
public $text = "用$this调用我";
public function output(){
echo $this->text;
}
}
构造方法(实例化时执行)
构造方法可以传递参数,在实例化时传入
通过构造函数的参数传递,改变里面的属性使得每个实例对象不同
class Computer{
function __construct($arg){
echo "我是构造方法,自动执行";
echo $arg;
} } $conputer = new Computer("我是构方法的参数");
析构方法:销毁时执行,不能有参数
程序结束后自动执行,手动释放(当对象的引用全部销毁时)会使析构函数提前执行,不用等到程序结束后才调用
当你 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了
//对象引用 在PHP 中引用的意思是:不同的名字访问同一个变量内容.
class A
{ function __destruct()
{
echo '====我是析构函数====';
}
} $a = new A();
//提前执行析构函数的两个方法 unset($a);$a=null;
echo "====正常执行我是先输出的=====";
//两种对象引种的区别
$a = $b;//这时$a和$b是两个独立的引用,unset($aa)只是删除了$a的引用,还有$b的引用,所以不会执行析构函数。改变其中一个为null,不会影响另外一个变量,也不会执行析构函数;
$c = &$a;//两个的变量使用同个引用,c是a的影子,改变其中一个变量为null,两个都为null,会执行析构函数。但是只是unset($a),$c还在使用引用,只要有引用在不会执行析构函数;
//对象的引用用于访问对象的属性和方法,所以$a $b $c都可以访问对象的属性方法;
//当一个对象的所有引用被删除后,才会触发析构函数 //总结:如果程序大,对象引用尽量使用&,节省内存,清除也方便。设其中一个为Null,其他都为Null; //变量引用 (默认变量赋值会独立开辟一个内存存放内容)
//PHP 的引用允许你用两个变量来指向同一个内容
$a="AB";
$b =&$a;
echo $a;//这里输出:AB
echo $b;//这里输出:AB
$b="EF";
echo $a;//这里$a的值变为EF 所以输出EF
echo $b;//这里输出EF<?php
$a
= 1;
$b
=
$a
;
echo
$a
;
//在此之前,b都是和a共用内存空间的。
xdebug_debug_zval(
'b'
);
$a
= 2;
//a作出了改变,此时b才会有自己的空间
xdebug_debug_zval(
'b'
);
?>
//函数引用
<?php
function test(&$a){
$a=$a+100;
}
$b=1;
echo $b;//输出1 test($b); //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了 echo "<br>"; echo $b;//输出101
?>
//函数的引用返回
<?php
function &test(){
static $b=0;//申明一个静态变量
$b=$b+1;
echo $b;
return $b;
}
$a=test();//这条语句会输出 $b的值 为1 相当于$a=$b
$a=5; $a=test();//这条语句会输出 $b的值 为2 也是$a=$b
$a=&test();//这条语句会输出 $b的值 为3 $a=&$b,所以b会随a变了
$a=5; $a=test();//这条语句会输出 $b的值 为6
?>
赋值和克隆的区别:
$a=$b(独立引用)和$a=&$b(同一引用)这种赋值方式,指向的是同一个对象,同一块内存空间;
$a=clone $b这种赋值方式,则是指向另一个新的对象,另一个块新的内存空间。
<?php class mm { public $name = 'Peter'; } $a = new mm(); $b = $a; $c = &$a; $d = clone $a; $b->name = "Anne"; echo $a->name,"\n",$b->name,"\n",$c->name,"\n",$d->name;//输出为:Anne Anne Anne Peter ?>
类常量
内部访问 self::常量名
外部访问不需要实例化:类名::常量名
class Computer{
const yh = 12;
const yh2 = self::yh+1;
}
var_dump (Computer::yh2);
$this 和 self 的区别
一个是对象$this 相当于实例化后,可以说除了静态和const常量,基本上其他都可以使用this联络 ;
self则是类本身 self可以访问本类中的静态属性和静态方法,可以访问父类中的静态属性和静态方法。用self时,可以不用实例化的
类的继承
存在意义:把相同的属性方法抽出来,让子类继承
extends 后只能一个逗号,就是说只能继承一个父类,单继承
class dad{
function eat(){
echo "我是父类的方法,子类可以继承我的方法";
}
} class boy extends dad{
}
$boy = new boy();
$boy->eat();
子类也可以覆盖父类的方法
子类没有构造方法时,会调用父类的构造方法,有则调用自己的,
用关键字 parent:: __construct();可以调用父类的构造方法
用final关键字加在类前面就不会被继承;加到方法面前,此方法就不会被重写
命名空间(解决命名冲突问题)
利用文件系统不用目录的原理
被引入的php文件中加入 namespace 目录\子目录;
使用时调用:new 目录\子目录\类名();如 new com\session\computer();
受命名空间影响的有,类(包括抽象类,traits),接口,函数,常量(const和define都是用来声明常量的(它们的区别不详述),但是在命名空间里,define的作用是全局的,而const则作用于当前空间。)
要注意的是,当前脚本文件的第一个命名空间前面不能有任何代码,下面的写法都是错误的:
//例一
//在脚本前面写了一些逻辑代码 <?php $path = "/"; class Comment { } namespace Article; ?> //例二
//在脚本前面输出了一些字符 <html></html>
<?php namespace Article; ?>
为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。
<?php
//创建一个名为'Article'的命名空间
namespace Article;
//此Comment属于Article空间的元素
class Comment { }
//创建一个名为'MessageBoard'的命名空间
namespace MessageBoard;
//此Comment属于MessageBoard空间的元素
class Comment { }
?>
由于每次调用都要写上路径,很麻烦,所以出现use的用法(use引入必须带类名或者函数名)
在调用时先用use引入,use 目录\子目录\类;还可以起个别名区别 as
use venter\session\computer;
use venter\computer as computer2;
new computer();
new computer2(); 函数的话记得带上function
use function venter\session\computer;
computer(); 常量记得带上const
use const venter\session\computer;
var_dump(computer);
重点:在命名空间里面调用全局的类,函数,常量的区别,
页面a定义了命名空间 namespace venter;引入b页面(全局空间)后,此时想调用b页面的类,必须:
New \venter() 加个\代表全局空间下的
但是调用函数和常量时,就不需要加,因为他会自动寻找,向全局寻找。
类自动加载:
当你实例化一个类时,这个类不存在,就会自动执行我们写的 function __autoload($className){},在这个自动函数的内部去执行我们想要操作的代码,参数就是我们实例化的类名,因此可以根据参数去引入php文件。
__autoload将被淘汰,使用新的函数 spl_autoload_register();参数可以传函数名或者匿名函数
spl_autoload_register(function($a){
echo $a;
}
);
new Computer();
或者
function aaa($a){
echo $a;
} spl_autoload_register('aaa');
new Computer();
或者类的调用方法
class momo
{
function aaa($a){
echo $a;
}
}
spl_autoload_register([new momo],'aaa');
new Computer();
利用命名空间和自动加载实现项目自动引用
1,文件目录就和命名空间名一样,文件名和类名一样 new models\imooc() 就是在models文件下的imooc.php文件,
2,然后利用spl_autoload_register(function($classname){
include str_replace("\\","/",$classname.".php");
});
这里的作用是models\imooc替换掉models/imooc.php 引入
而imooc.php文件中必须命名 namespace models;
static 静态
存在的价值,为了让对象公用一些数据,做到统一性
当属性和方法被定义为 static 时就变成类的属性和方法,不属于对象的,不需要实例化
外部访问 类名::$aa 内部访问 self::$aa 或者static::$aa; 子类访问父类 parent::$aa;
静态方法不能调用非静态属性
因为 $this代表实例化对象,而这里是类,不知道 $this 代表哪个对象
class person{
public static $aa ="a";
public static function eat(){
echo self::$aa;
echo static::$aa;
}
}
class boy extends person{
public function eat2(){
echo parent::$aa;
}
}
echo(boy::eat2());
后期静态绑定:
class A{
public static function who(){
echo "A类的who方法";
}
public static function test(){
self::who();
// static::who();
} }
class B extends A{
public static function who(){
echo "B类的who方法";
}
}
B::test(); 如果是self::who(); 输出的是A类的who方法,说明调用的是A自身,static::who();会根据上下文作处理,类B调用就使用B里面的who()
魔术方法
__set($var,$val) 设置私有属性,当外部调用设置一个私有属性时会自动执行这个方法,
__get($var)获取私有属性,原理是外部调用一个私有属性时会自动执行这个方法
例子:
class test{
private $abc = "";
private $ccc = "";
public function __set($var,$val){
$this->$var = $val;
}
public function __get($var){
return $this->$var;
}
}
$test = new test();
$test->abc = 'abc';
var_dump($test->abc);
__isset($var)方法,当外部调用isset($test-abc)访问一个不能访问的属性时,就会自动执行 isset()或者empty() 都会触发__isset()方法
__unset($var),当外部想删除一个私用属性时,会自动执行
以上是属性的重载
__call,__callStatic是属于方法的重载,不是重写
__call($func方法名,$arguments参数)当外部调用一个没有定义的方法时,就会调用
__callStatic($meethod,$arg)当调用一个不存在的静态方法时,会自动执行 注意在function 前也要加入 static 因为是静态方法
__invoke($rag)当实例化一个类后,把这个对象变量当成函数调用时,会自动执行
例如:$test = new test();
$test("go....");
__toString() 当对象被当成string使用时,会执行,比如 echo($test);
__clone方法的一些应用
当一个对象被克隆时,会调用__clone,此时可以在里面执行一些逻辑,比如不想让某些值被克隆,或者初始化一些属性的值
对象拷贝:
浅拷贝:是地址传递(对象是浅拷贝)
深拷贝:复制一份,新开辟一块内存(普通变量是深拷贝)
加clone 使对象成为深拷贝,互不影响;
$a = new A();
$b = clone $a;
__clone()当使用clone时,会自动执行
$a = new A();
$b = clone $a; 在A类中会执行__clone()
例子:
class A{
public $obj = null;
public function __clone(){
$this->obj = clone $this->obj;//开辟了新空间给克隆的对象
}
}
Class B{
public $sex = 0;
} $a = new A();
$a->obj= new B();
$b = clone $a;
$b->obj->sex = 1;
var_dump($a->obj->sex);
类型约束
class A{
public $obj = null;
public function go(){
echo "googogogogo";
}
}
class B{
public function go(){
echo "bbbbbb";
}
}
Function test(A $a){
$a->go();
}
test(new A());//必须是A的实例
trait 关键字
解决单继承问题 配合use 使用
trait A{
public function a(){
echo "aaaaa";
}
}
trait B{
public function b(){
echo "bbbb";
}
} Class test{
use A,B;
public function c(){
echo "cccc";
}
} $test = new test();
$test->a();
$test->b();
$test->c();
接口
可以理解为类的模板 不能直接被实例化
用instanceof 判断某个对象是否实现了某个接口
接口可以继承接口,但是类必须实现接口所有的方法
interface person {
public function eat();
public function sleep();
}
class man implements person{
public function eat(){
echo "chichi吃吃";
}
public function sleep(){
echo "shuishushi";
}
}
$aaa = new man();
$aaa->eat();
//接口继承 两种方法
interface aa {
public function eat();
}
interface bb {
public function sleep();
}
interface person extends aa,bb{
//person就直接继承了两种方法
}
class man implements person{
public function eat(){
echo "chichi";
}
public function sleep(){
echo "shuishuishui";
}
}
//或者 直接实现两种接口
class man implements aa,bb{
public function eat(){
echo "chichi";
}
public function sleep(){
echo "shuishuishui";
}
}
//接口里面可以利用 const 定义一个常量
interface person {
const aa = "bbb";
public function eat();
public function sleep();
}
echo person::aa;
抽象类:
(比如人和动物都会呼吸方法都一样,此时就不需要每个类去实现不同的呼吸方法,吃东西的方法不同,所以在类中各自实现逻辑)抽象类的子类只需要实现抽象方法;
内部有自己的执行方法
abstract class person {
public function holiday(){
echo '我是抽象类自己实现的方法';
}
//抽象方法,以分号结束,无方法体;抽象类中至少要有一个抽象方法
abstract public function eat();
}
class man extends person{
public function eat(){
$this->holiday();//直接调用即可
}
}
$aaa = new man();
$aaa->eat();
单例模式:
让一个类只会被实例化一次,节省内存空间
先把构造函数和克隆函数变成私用属性
class test{
private static $_instance = null;//依靠属性存储实例对象判断是否已经实例过
private function __construct(){
// 私有后将不会被外部实例
}
private function __clone(){
// 私有后将不会被外部克隆
}
public static function getInstance(){
if(!(self::$_instance instanceof self)){
// instanceof判断是否是当前的实例,不是的话就实例化赋值,否则就返回
self::$_instance = new self();
}
return self::$_instance;
}
}
$test1 = test::getInstance();
$test2 = test::getInstance();
$test3 = test::getInstance();
var_dump($test1);
var_dump($test2);
var_dump($test3);
// 输出结果object(test)#1 (0) { } object(test)#1 (0) { } object(test)#1 (0) { }
工厂模式:
就是在多处实例化一个类,当这个类名需要改变时,就会导致大量地方需要更改,使用工厂模式避免这种情况发生
class A{
public function a(){
echo 'aaa';
}
public function c(){
echo 'ccc';
}
public function b(){
echo 'bbb';
}
}
class cashe{
public static function factory(){
return new A();//当业务逻辑变化时,只需要改此处
}
}
$cashe = cashe::factory();
$cashe->a();
面向对象功能汇总
有继承功能,必须有访问的控制,(私有公有属性),static静态关键字来保存一些公用的数据,重写对父类的方法属性重定义,final关键字不允许重写或者继承,访问静态属性的几个方法,接口中的方法是不用具体实现的,在类中才实现,而且必须实现接口中所有的方法,因为有了不同的实现方法逻辑,不同的对象产生不同的表现,这叫多态,存在与接口与类之间的叫抽象类,可以有一部分可以实现,一部分不用实现
/*--------------多态的一个应用实例 模拟USB设备的使用------------------*/
//一个USB的接口 interface USB{ function mount();//装载USB的方法 function work();//USB工作的方法 function unmount();//卸载USB的方法 } //定义一个USB设备 U盘 class Upan implements USB{//实现USB接口 function mount(){ echo " U盘 装载成功<br/>"; } function work(){ echo "U盘 开始工作<br/>"; } function unmount(){ echo "U盘 卸载成功<br/>"; } } //定义一个USB设备 USB鼠标 class Umouse implements USB{//实现USB接口 function mount(){ echo " USB键盘 装载成功<br/>"; } function work(){ echo "USB键盘 开始工作<br/>"; } function unmount(){ echo "USB键盘 卸载成功<br/>"; } } //定义一个电脑类 class Computer{ //使用USB设备的方法 function useUSB ($usb){//$usb参数表示 使用哪种USB设备 $usb->mount();//调用设备的 装载方法 $usb->work();//调用设备的 工作方法 $usb->unmount();//调用设备的卸载方法 } } //定义一个电脑的使用者的类 class PcUser{ // 安装 USB的方法 function install(){ //首先拿来一台电脑 $pc=new Computer; //拿来一些USB设备 $up=new Upan;//拿来一个U盘 $um=new Umouse;//拿来一个USB鼠标 //把USB设备插入电脑, 使用电脑中使用USB设备的方法 来调用 要插入的设备 $pc->useUSB($up);//插入U盘 $pc->useUSB($um);//插入USB鼠标 } } //实例化一个电脑用户 $user=new PcUser; $user->install();//安装设备 /*-------------输出内容-------------- U盘 装载成功 U盘 开始工作 U盘 卸载成功 USB键盘 装载成功 USB键盘 开始工作 USB键盘 卸载成功 -----------------------------------*/ ?>
PHP面向对象的小总结的更多相关文章
- Java学习笔记二十九:一个Java面向对象的小练习
一个Java面向对象的小练习 一:项目需求与解决思路: 学习了这么长时间的面向对象,我们只是对面向对象有了一个简单的认识,我们现在来做一个小练习,这个例子可以使大家更好的掌握面向对象的特性: 1.人类 ...
- 分享几个原生javascript面向对象设计小游戏
一.序言 不知大家是不是和我一样,当初都有个梦想.学编程,就是想开发游戏.结果进入大学学习之后,才知道搞的是数据库应用程序开发!在此,本人就分享下业余时间做的几个小游戏吧!本打算想用winform或w ...
- Java 面向对象编程小练习(曾经)
最近打算将之前学习过的小练习分享出来,算是巩固知识.虽然是小练习,但是越看越觉得有趣,温故而知新. 练习:功能跳水比赛,8个评委评分.运动员成绩去掉最高和最低之后的平均分 代码实例: 1.导包 imp ...
- JavaScript面向对象编程小游戏---贪吃蛇
1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1- 2 维护非常方便并且成本较低. 2 这个demo是采用了 ...
- python 面向对象编程 - 小游戏
面向对象写的小游戏 欢迎玩耍 class Omnicience: camp = 'Omniscience' def __init__(self, name, atk=100, hp=1000, mp= ...
- pyhton 面向对象之 小明左右手换牌
'''#左右手交换牌 案列#小明手里有俩张牌,左手红桃♥K,右手黑桃♠A,小明交换俩手的牌后,手里分别是什么? 人类: 属性:小明,左手,右手 行为:展示手里的牌, 交换手里的牌手类: ...
- Python - 面向对象编程 - 小实战(1)
题目 设计一个类Person,生成若干实例,在终端输出如下信息 小明,10岁,男,上山去砍柴 小明,10岁,男,开车去东北 小明,10岁,男,最爱大保健 老李,90岁,男,上山去砍柴 老李,90岁,男 ...
- Python - 面向对象编程 - 小实战(2)
需求 小明和小美都爱跑步 小明体重 75 公斤 小美体重 45 公斤 每次跑步会减肥 0.5 公斤 每次吃东西体重增加 1 公斤 需求分析 小明.小美都是一个具体的对象,他们都是人,所以应该抽象成人类 ...
- 面向对象的小demo
两个类如下 package cao.com.duixiang; import java.util.Arrays; public class OtherTest { //求max public int ...
随机推荐
- 汉诺塔问题其实很简单 Python 递归经典面试题
话不多说,上代码 1 def hanoi_move(n, source, dest, intermediate): 2 if n >= 1: # 递归出口,只剩一个盘子 3 hanoi_move ...
- Python内置函数(45)——object
英文文档: class objectReturn a new featureless object. object is a base for all classes. It has the meth ...
- 8.Django缓存和信号
缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将某个views的返回值保存至内存或者memcache中, ...
- GitLab 社区版 11.0.2用户管理教程
Gitlab地址:http://xx.xx.xx.xx/users/sign_in 登录之后,主界面 右上角功能按钮,分别为管理区域.新建.问题.合并请求.待办事件.个人设置 选择管理区域按钮 可以根 ...
- NodeJs安装步骤与淘宝镜像
dir 列目录 lscd 路径 切换路径 cdmd 文件夹名 创建一个空文件夹 mdC: 切换盘符 cls 清屏 clear ping ip/网址 网络测试ipconfig -all 查看网络连接信息 ...
- qt系统托盘显示、无主窗体
系统图盘是应用程序经常用到的一个控件,当应用程序需要长时间存在的时候,这个控件会变得非常有用,比如,窗口隐藏,显示,关于.关闭等接口都可以放在图盘中处理,今天与到一个问题,需求是这样的:只需要显示图盘 ...
- SpringBoot入门教程(十四)导出Excel
用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...
- java 取汉字首字母
有时候,可能会有一些类似这样的需求: 对于这样的效果,我们可以有类似这样的解决方案: package bys.utils; import java.io.UnsupportedEncodingExce ...
- 带着萌新看springboot源码03
上一节讲到了快速新建一个springboot应用,以及springboot的自动配置类起作用的时机,并且一起看了一个自动配置类的源码. 这一节我们来粗略看看当用户在浏览器输入一个url,怎么样返回一个 ...
- Python:游戏:测试打字速度
现在写书的人真是一点责任心都没有,最近看了几本书,其中的代码都存在错误. 最近迷恋 Python 游戏,买了<Python游戏编程入门>[美] Jonathan S·Harbour 著 一 ...