什么是类?类就是对象的蓝图,对象就是类的实现。类的声明很简单:
【一些修饰类的关键字】class 类名{
…… //需要注意类名的股则和变量名相似,但要有意义,习惯上由几个单词组成,而且每个单词首字母要大些
}
类中的内容分为两部分,成员属性和成员方法。成员属性的声明方式: 修饰关键字 $name;或者声明时就赋值:修饰关键字 $name=”happy”; 需要注意一点修饰关键字不能省略。成员方法的声明方式和普通函数类似,只不过前面可以加个修饰关键字。
【修饰关键字】function(){
……
}
什么是对象?对象是PHP8中数据类型中的一种,和数组一样也属于符合数据类型。面向对象的的基础就是对象。实例化对象需要用到类,加入声明好一个类了。实例它的方式就是
$变量名= new 类名称(【参数列表】);或者 $变量名=new l类名称;
对象在内存中的分布:对象存储在堆内存中,类中的函数存储在代码段内存中,静态变量和方法以及类中的常量(后面讲)存储在数据段中。而引用类的变量名存储在栈空间段中(先进后出)。
对象中成员的访问,你用一个变量名实例化一个对象后吗,就可以访问里面的成员了,对于变量可以访问,也可以写(当然还得看变量前的关键字)。访问:echo $引用名->成员属性;写的操作:$引用名->成员属性=值;对于方法也可以这么访问,如果需要用的方法有返回值,可以直接用它,(把他的值赋给别的变量,或者把他的值echo出来).如果该方法直接是一段自行代码,用$引用名->成员方法();就可以让方法被执行。
如果有时后你在这个类中需要用到这个类中之前声明好的变量,或者方法。用$this->成员即可,需要讲明一点,这里的$this是代表本身这个对象,并不是本身这个类。
魔术方法大杂烩:
Php的魔术方法听说是独有的,其他大型语言中没有类似的魔术方法。第一个要说的就是构造方法,结构是:
function __construct([参数列表]){
…… //需要注意的是上面是两根下短横线,这个东西是一般用来对成员属性进行初始化赋值的
}
补充一下,构造方法是自动就要调用的。下面介绍一个对应的析构方法。通常对象中的引用被赋予其他的值的时候或者是在页面运行结束的时候,对象就会失去引用。PHP的垃圾回收机制就会自动启用,收回对象在对内存中占用的内存空间。析构方法则会在垃圾回收对象启用前执行。
function __destruct(){
……
}
补充一下,因为对象的引用都是存放在栈内存中的,所以由于先进后出的特点,最后创建的对象的引用会最先释放。
魔术方法 __set(),该方法有两个参数,属性名,值。当在对象外部为私有对象赋值时,自动调用。该方法可以控制外部为私有变量赋值。格式如下:
function __set($propertyname,$propertyValues){
……(在控制下为私有属性赋值)
}
魔术方法 __get(),该方法有一个参数。当直接在对象的外部获取私有属性的值时,会自动调用此方法。返回控制下的值。格式为:
Function __get($propertyname){
…… //自定义返回一个值
}
魔术方法 __isset(),当在类的外部使用 isset()函数来测定对象里的私有属性时们就会自动调用__isset()方法。格式如下:
function __isset($propertyname){
…… //决定返回什么
}
魔术方法 __unset(),当在累的外部用unset()函数来删除类中的私有变量时,就会自动调用__unset方法。格式如下:
function __unset($propertyname){
……//决定怎样删除,删不删这个变量
}
魔术方法__clone(),这个魔术方法就相当于,生成生成新类类时候的function __construct();只不过__clone()是用在克隆新对象的时候执行的
$a=new Person(“张三”,” 男”,20);
$b= clone $a;
魔术方法 __tostring(),当在php5 中直接echo $p;($p是一个对象)是会发生错误的,如果你有 __tostring()这个魔术方法就不一样了,你再去执行上面那个代码就会是正确的,所以一般来说这个方法都是返回一个关于这个类的一些属性的字符串。
魔术方法 __call(),当你尝试调用对象中不存在的方法,一定会系统报错,并退出程序不能继续执行。在php 中呢,__call(),则正好是调用对象中不存在的方法时会自动调用这个方法。__calss()方法需要两个参数,第一个是用于接受调用的不存在的方法的方法名,第二个是接受是以数组的形式接受调用不存在方法中的参数。
讲面向对象三大特性(封装性,继承性,多态性)之前还是将几个属性和方法之前的权限关键字关键字:
关键字 | 本类 | 子类 | 外部 |
public(老版用var) | OK | OK | OK |
protected | OK | OK |
|
private | OK |
|
|
好现在开始说封装性:一句话封装性的原则就是不让对象以外的部分随意存取对象的内部数据(属性和方法)。从而有效的避免外部错误对它的交叉感染,使错误能够局部在类中。使用private关键字就能实现成员封装。封装后的成员在对象的外部不能访问,但在对象的内部成员方法中可以访问。私有成员成员的访问就可以通过这种方式,用这种接口(公有的方法)规范对私有成员的访问。
好,现在来讲继承性,三大特性之一,建立一个新的派生类,从一个先前定义的类中继承数据和函数,而且可以重新定义和改进这个函数。继承的格式
Class teacher extends person{
……
}
继承之后先前person类中除了private限制的成员,teacher类中都有了。如果你想扩展(重载)某个方法的话,你可以在新类中写一个同名的方法,但前面的修饰词的权限问题,一定要注意,子类中重写的方法的访问权限一定不能低于父类中被覆盖的方法的访问权限。
顺带提一下,另外几个关键字
fina 这个是php5中增加的,它可以加在类或者类中的方法前,但切记不能用来表示成员属性哈。这个关键字的作用,使用fina标识的类,不能被继承。在类中使用fina标识的成员方法,在子类中不能被覆盖。
Static,这个关键字很重要,使用这个关键字,可以将类中的成员和方法标识为静态的。类的静态属性非常类似于函数中的全局变量。类中的静态成员是不需要对象而使用类名直接访问的。在类中申明的成员方法中,也可以使用关键字”self” 来访问其他静态成员。因为静态成员是属于类(存在内存中的数据段的)的,所以你不能使用$this来引用它,所以php给我们提供了self,这个意思就是用来代替本类。在类中的外部访问静态成员,可以使用对象引用也可以使用类名访问(类名访问要加::)。在类内部的尽量用self而不要用类名。
最后要强调一点:在静态方法中只能访问静态成员(其实我跟觉得是存放在内存数据段的东西,因为后面的常量也可以访问。)
顺带提一下单态设计模式,这个意思就是必须让一个类只能实例化一个对象。模式:不能在类中的外部直接是哟个NEW关键字去实例话这个对象,可以让这个类的构造方法private。但为了能实例化这个类,我们需要创建一个静态的方法(第一次实例都没对象,需要用类引用),用这个方法来实例这个类。在这个方法中判断类是不是已经实例化一次了,如果不是就实例,如果是就还是引用之前实例了的那个对象。这需要一个变量引用,而且要在类没有被实例的时候能用,所以必须用静态属性。、
Const 关键字,和static声明的属性一样都是存在内存的数据段中的。所以使用方法和static相同,需注意的是表示为常量的属性是只读的,不能重新赋值,所以一定要给初值,还有
使用const声明的变量名称前不要加$,而且这个变量名通常是大写的。格式
const DAFANZI = “we are very happy”;
Instanceof关键字 ,这个关键字可以确定一个对象是类的实例,类的子类,还是实现了某个特定的接口,并进行相应的操作。需要注意这里的类和对象均不需要“”.格式:
If($man instanceof Person){
……
}
好,现在讲克隆这个特性了,需要记住,$a=new Person; $b= $a;这不是复制(克隆),内存的堆内存中还是只有一个对象。你要克隆的话,就需要用clone 关键字,格式:
$a=new Person(“张三”,” 男”,20);
$b= clone $a;
这样就形成了两个相互独立的,但内容完全一样的两个对象了。如果需要克隆后有什么改变,可以用__clone()方法,这个魔术方法就相当于,生成生成新类类时候的function __construct();只不过__clone()是用在克隆新对象的时候执行的。
---------------------------------------------------------------------------------------------------------------------------------
好,现在开始讲抽象类了。首先,抽象方法就是没有方法体的方法,就是在方法声明的时候没有花括号以及花括号内的内容,而是在方法名后直接加;另外在声明抽象方法时,还要使用关键字abstract关键字修饰,只要声明类的时候有一个方法是抽象方法,那么这个类就是抽象类。抽象类也要使用abstract 关键字来修饰。在抽象类中可以有不是抽象的方法和属性,但访问权限不能使用private来修饰为私有的。当子类继承抽象类后,就必须把抽象类中的抽象方法按照子类的需要全部实现,如果没有全部实现,则子类中还存在抽象方法,则这个类还是抽象类,还是不能实例化对象。
现在讲接口,接口可以说是一种特殊的抽象类。接口的要求是类中全部是抽象的方法,因为全都是抽象的方法,所以abstract 就不用写了。另外接口中不能声明变量,只能使用const 关键字声明为常量的成员属性。而且类中的成员都必须有public的访问权限。并且接口不再用class标识了,应该用interface标识。格式
Interface 接口名称{
常量成员
抽象方法
}
接口和抽象类一样不能实例化对象。但可以直接使用接口名称在接口外面去获取常量成员的值,也可以用extends关键字让一个接口去继承另一个接口,实现接口之间的扩展。例子
Interface two extends one{
抽象方法
常量成员
}
如果是普通类或者是抽象类继承继承接口的话,则必须用implements,如果是普通类继承接口,则要求实现接口中的所用抽象方法。抽象类可以只实现部分接口中的抽象方法。一个类只能有一个父类,单一类可以有多个接口,格式为
Class 类名 implements 接口一,接口二,接口n{
}
一个类还可以既继承父类又可以继承接口。格式为
Class 类名extends 父类名 implements接口一,接口二,接口n{
……//必须先继承父类,再继承接口。
}