1.面向对象概念1.1什么是面向对象(objectoriented)世界万物皆对象,抽象也是对象,凡是可见或不可见的都是对象1.2对象的基本构成对象由两部分组成:对象的构成元素是对象的数据模型,用来描述对象的数据是也称为对象的属性,或者说对象的成员变量的行为是对象用来描述一个对象可以做什么的行为模型,也称为对象的方法。1.3对象特征每个对象都是独一无二的。对象是具体的事物,其功能是完成特定的功能。该对象可以重复使用。1.4面向对象简介面向对象编程是指在编程时,通过对象的结构来存储数据结构(数据组织方式),并使用属性和方法进行组织。为什么要使用面向对象编程?对象描述方法更适合现实世界,有利于大规模业务的理解出来。对象之间的交互是通过方法调用完成的。1.6面向对象的基本思想识别对象任何实体都可以被识别为对象。识别对象的属性。存储在对象中的数据被标识为属性。对于不同的业务逻辑,关注的数据不同,对象存储的属性也不同。识别对象的行为。对象自身的属性数据发生变化。对象外部的交互。1.7面向对象对象的基本原则。)所有与对象相关的内容都被封装到对象内部对象外部低耦合外部世界可以看到对象的一些属性(不是全部)外部世界可以看到对象可以做某些事情(不是全部)软件设计一样多aspossible:高内聚,低耦合,模块与模块应该是独立的,没有依赖关系2.面向对象的基本实践2.1类的概念像对象一样集群,将具有相似特征的对象配对成一个类类定义这些相似的对象相同类所拥有的属性和方法是对相似对象的描述,成为类的定义,对象的蓝图或原型类称为类实例(Instance)。类的属性和方法统称为类成员2.2Class实例化类的实例化:通过类定义创建类对象。类定义的属性值都是空值或默认值,对象的属性是有具体值的。2.3类定义类的定义以关键字class开头,后面是类名。类的名称通常每个单词的首字母大写,以方括号开头和结尾将类实例化为对象时,使用关键字new,后面跟着类的名称和类中的成员属性和方法一对括号可以通过->符号访问。2.4构造函数对象实例化时会自动调用默认的构造函数。$this是Php中的伪变量,代表对象本身。通过$this->可以访问对象的属性和方法。每次用new实例化一个对象时,都会调用类名后面的参数列表构造函数。调用2.5析构函数__destruct(){}析构函数采用后进先出的原则。有两种方法可以执行析构函数:将对象设置为非空或程序结束时自动调用析构函数,系统占用的资源被系统回收。析构函数通常用于清理程序使用的资源,如释放打开的文件等,当对象将不再使用时自动调用析构函数。如果是复制,而不是&引用,则不会调用析构函数2.6对象&引用的基本概念$james1=$james;//相当于多复制了一个引用,两者是独立的两个引用$james2=&$james;//相当于给james取了别名,两者其实是一个,只是有两个名字特别注意:PHP总是会通过引用传递对象(ArrayObject是一个SPL对象,完全模仿了数组的用法,只不过是Work带对象)$arr=array();$arr2=$arr;$arr2是$arr数组的副本,它们互不影响,它们是独立的两个数组&对象(数组)是等价的深入理解PHP从别名引用:常见错误#3:通过引用返回的困惑并按值返回三、面向对象进阶实战3.1对象的继承父类:有一些相同的属性和方法在父类中继承的好处定义的类成员不需要在子类中重复定义,节省了编程时间和成本。同一个父类的子类具有父类定义的相同的类成员,所以当外部代码调用它们时,子类可以被同等地修改。而调用父类定义的类成员就叫做覆盖(Overwrite)。子类一旦修改,就会按照子类修改后的函数执行子类:子类可以通过$this访问父类的属性子类的对象可以直接调用父类PHP的方法和属性单继承特性:类不允许同时继承多个父类(extends后面只能跟一个父类名)3.2访问控制面向对象的三种访问权限:public是公共类的成员,可以是任何地方访问都可以被类和子类或对象访问protected受保护的类成员可以被自身访问,继承的子类可以被子类继承,但不能可以被对象访问,对象只能通过封装访问private私有类成员。只能自己访问,不能被子类继承,也不能被对象访问。只能通过封装被外界访问(比如在类中定义一个公有方法来调用私有属性)3.3Static(静态)关键字静态成员:定义时在访问控制关键字后面加上static关键字(访问控制关键字:public.protected.private)静态属性用来保存类的公共数据,可以在不同对象之间共享。静态方法只能访问静态属性。静态成员可以在不实例化对象的情况下访问类的内部。可以通过self::或static::关键字访问自己的静态成员,self::$属性self::方法()通过parent::关键字访问父类的静态成员,或者访问外面的静态成员类通过子类::父类静态成员通过类名::方法3.4重写在子类中用Final关键字写一个和父类一模一样的方法,完成父类方法的重写。方法参数最好有默认参数。对于不想被任何类继承的类,可以在类前加上final关键字。对于不想被子类覆盖(overwrite、modified)的方法,可以在方法定义前加上final关键字3.5数据访问parent关键字可以用来调用父类中的方法被子类覆盖self关键字可以用来访问类本身的成员方法、静态成员和类常量;不能用于访问类本身的属性!!!使用常量时,不需要在常量const名前加$符号。static::关键字用于访问类本身定义的静态成员。访问静态属性时,需要在属性前加上$符号。常量属性const不能用于对象访问,只能使用类访问,可以在类本体内部使用“self::constantname”,在类本体外部使用“classname::constantname”。3.6对象接口接口就是定义不同类的共同行为,然后在类中实现不同的功能。interface定义了接口,implements用来表示该类实现了某个接口。接口中的方法没有具体的实现,也没有{}实现了某个接口的类必须提供接口中定义的方法的具体实现,不能是实例接口,但可以判断一个对象是否实现了一个一定的界面。instanceof关键字判断一个对象是否实现了一个接口$objectinstanceofinterfaceinterfaceinterface可以继承接口(interfaceextendsinterface)接口中定义的所有方法必须是public的,这是接口的特性3.7多态性因为接口的方法是implemented可以有很多,所以接口中定义的方法的具体实现是多种多样的。我们称之为特征多态性。您不需要知道对象属于哪个类。只需要判断对象的类是否实现了接口,就可以调用了,同样的代码实现不同的结果直观上来说就是同一个接口,不同的对象实现,不同的结果就是多态,比如输入是人对象,结果是人吃苹果,输入是猴子对象,结果是猴子吃香蕉。同一行代码在传入实现不同接口的对象时表现不同。/***多态性*1.对象只要实现了接口(instanceof),就可以直接调用对象上接口的方法*/interfaceICanEat{publicfunctioneat($food);}//Human类被实现ICanEatinterfaceclassHumanimplementsICanEat{//Animal类的实现不同publicfunctioneat($food){echo"Humaneating".$食物。"\n";}}//Animal类实现ICanEat接口classAnimalimplementsICanEat{publicfunctioneat($food){echo"Animaleating".$食物。"\n";}}functioneat($obj){if($objinstanceofICanEat){$obj->eat("FOOD");//不需要知道是Human还是Animal,直接吃就可以了}else{echo"Can'teat!\n";}}$man=newHuman();$monkey=newAnimal();//相同的代码,当传入接口的不同实现类时,表现不同。这就是为什么它被称为多态性。吃($人);吃($猴子);3.8抽象类接口中的方法没有实现,但是类中的方法都实现了。有没有一种形式可以让类中的某些方法不被实现?当接口中的一些方法对所有的实现类都是相同的时候,只有一些方法需要使用多态特性。比如人和动物吃的东西不一样,但是呼吸一样,人和动物没有必要。abstract关键字用于定义抽象类。在抽象方法前加上abstract关键字可以表明该方法是一个抽象方法,不需要实现{}抽象类可以包含普通方法,方法的具体实现继承抽象的关键字类是extends抽象类的子类,需要实现抽象类中定义的抽象方法抽象类不能被实例化。子类继承抽象类时,必须定义所有抽象方法/***abstractClass*1.抽象类允许类中的某些方法暂时未实现。我们把这些方法称为抽象方法*2.类中一旦有抽象方法,那么这个类就一定是抽象类*3.抽象类和接口一样,不能直接实例化为对象*///abstractclass以abstract关键字开头abstractclassACanEat{//没有实现的方法需要设置为抽象方法//抽象方法需要在子类中实现abstractpublicfunctioneat($food);publicfunctionbreath(){echo"用空气呼吸。\n";}}//Human类实现了ICanEat接口classHumanextendsACanEat{//不同于Animal类的实现publicfunctioneat($food){echo"Humaneating".$食物。"\n";}}//Animal类实现了ICanEat接口classAnimalextendsACanEat{publicfunctioneat($food){echo"Animaleating".$食物。"\n";}}$man=newHuman();$man->eat("Apple");$man->breath();//与Animal共享抽象类ICanEat的breath方法$monkey=newAnimal();$猴子->;吃("香蕉");$猴子->呼吸();四、PHP面向对象的特殊实践4.1魔术方法_toString()和invoke()__toString()当对象作为String使用时,该方法会被自动调用(需要在类中定义__tostring()方法classtocallecho$object__invoke()当对象作为方法调用时,会自动调用该方法(需要在类中定义__invoke()方法)调用$object($parameter)/***Magic方法1*1.当对象作为String使用时,自动调用__toString()*2.当对象作为方法调用时,自动调用__invoke()*/classMagicTest{publicfunction__toString(){return"ThisistheClassMagicTest.\n";}publicfunction__invoke($x){echo"__invokecalledwithparameter".$x."\n";}}$obj=newMagicTest();echo$复制代码obj;$obj(5);4.2魔术方法的__call()和__callStatic()__call()方法:当对象访问一个不存在的方法名时,调用这个方法automa很明显。调用示例:publicfunction__call($name,$argument){}注意:访问控制关键字必须是public;必须有两个参数:对象访问的方法名($name),方法中包含的参数($argument==>自动转成数组)。__callStatic()方法:当对象访问一个不存在的静态方法名时,自动调用该方法。调用示例:publicstaticfunction__callStatic($name,$argument){}注:与__call()相同;这个方法是一个静态方法(static)。这两种方法也称为方法重载(overloading)。注意区分覆盖(overwrite)。通过这两个方法,同一个方法的调用可以对应不同方法的实现(同一个方法的静态调用和动态调用对应不同的方法实现)/***魔术方法的方法重载*1.当一个对象访问不存在的方法名,会自动调用__call()方法*2.当对象访问不存在的静态方法名时,会自动调用__callStatic()方法*/classMagicTest{/***自动将参数转换成数组*array(size=2)*0=>string'para1'(length=5)*1=>string'para2'(length=5)*@param$name*@param$arguments*/publicfunction__call($name,$arguments){var_dump($arguments);回声“呼唤”。$名字。"带有参数:".内爆(',',$arguments)。"\n";}publicstaticfunction__callStatic($name,$arguments){echo"静态调用".$名字。"带有参数:".内爆(',',$参数)。"\n";}}$obj=newMagicTest();$obj->runTest("para1","para2");MagicTest::runTest("para3","para4");4.3魔术方法当__get(),__set(),__isset()和__unset()为不可访问属性赋值,__set()会调用定义函数__set($name,$value)读取不可访问属性的值时,会调用__get()定义函数__get($name)当在不可访问的属性上调用isset时()或empty(),__isset()将被调用。当对不可访问的属性调用unset()时,将调用__unset()。这些方法也称为属性重载的魔术方法。所谓不可访问的属性,其实就是调用一个属性的时候,发现这个属性没有定义。这时候不同的操作会触发不同的法术。4.4魔术方法的__clone()$obj1=$ojb;对象变量指向同一个对象$obj1=clone$obj;//实现对象复制,成为两个具有相同值的对象调用clone时,会自动调用__clone()方法$james=newNbaPlayer();//$ja0对应james对象的标识符存放在内存地址(假设为address0)$james2=clone$james;//当你想生成一个真正独立存储的NbaPlayer()对象,但是新对象的所有数据都和$james对象中的一样时,使用关键字clone,当__clone()方法定义在classNbaPlayer(),当使用clone关键字时,系统会调用用户自定义的__clone()方法(可以修改新对象的属性)完成!参考教程:PHP面向对象编程
