php面向对象
目录
1. 面向对象典型例子
//一个典型的类
class Person{
//注意这里用var定义,未确定用哪个关键词(protected,private,public)来修饰
var $name ;
//构造函数,
function __construct($name){
//通过构造函数传参来给类中的属性赋值
$this->name = $name;
}
//说话这个方法
function say(){
echo "我的名字是".$this->name;
}
//实例化类.实例化后人就有了自己的专有特征,下面三个实例是不同的
$people1 = new Person("王王","男",20);
$people2 = new Person("李李","女",21);
$people3 = new Person("张张","男",22);
//每个具体的人都有自己的说法方式,能说出不同的内容
$people1->say() //我的名字是王王
$people2->say() //我的名字是李李
$people3->say() //我的名字是张张
总结:
- 一个类,可以有自己的属性,自己的方法,我们可以在构造函数中实现很多方法
- 实例化类是用new关键字,并且可以传入参数
- 访问这个实例化后的具体对象的方法是: 对象->属性 =xxxx
- 类和对象就像是,图纸和房子的关系,我们按照图纸施工就得到了一个有血有肉的真实的房子.这个过程就像是实例化,实例化后我们就可以在房子里做饭,洗衣服...
2. $this关键字
- $this在构造函数中指代该构造函数所创建的新对象,就是指当前对象
- 在当前类中使用属性和方法, $this->属性 或者 $this->方法
- 对象的方法内的局部变量,只在当前方法内有效,所以不使用$this关键字,直接使用
- 局部变量和类的属性要认清,可以同名,但是要注意区分,尽量不同名,以免混淆
class Person{
var $name = "李四" ;
function say($name){
echo "我是类的属性中的name".$this->name;
echo "我是say方法中传递过来的参数".$name;
$this->dacnce(); //同样我们可以在say方法中调用person类中的dance方法;
}
function dance(){
echo "我会跳霹雳舞";
}
}
$people = new Person();
$people->say('张三');
//注意这里和上面例子中的区别,上面是在人实例化的时候就传入了初始属性,这里是给人的方法传入参数,注意理解
3. $parent关键字
- parent用来引用父类的方法
- parent::的追溯不仅于直接父类
## 一.子类继承父类
## 例子1
//父类
class employee{
protected $sal=3000;
public function getSal(){
$this->sal = $this->sal + 1200;
return $this->sal ;
}
}
//子类对父类继承
class Manager extends employee {
public function getSal(){
// 这里调用了父类的方法,
parent::getSal();
//employee类中的return $this->sal 是为echo服务的
//下面的$this->sal中的sal是通过继承得到的,而不是return回来的
$this->sal = $this->sal + 1500;
return $this->sal ;
}
}
$emp = new employee();
echo "普通员工的工资是 " . $emp->getSal();
$manager = new Manager();
echo "经理的工资是: " . $manager->getSal();
//普通员工的工资是 4200
//经理的工资是: 5700
## 二.子类对父类属性重写
## 例子2.1
//父类的private属性不能被继承,如果父类有私有属性,那么父类的的方法只为父类的私有属性服务
//父类 private $sal =3000
//子类 protected $sal = 5000
class employee{
private $sal=3000;
public function getSal(){
return $this->sal ;
}
}
class Manager extends employee {
protected $sal=5000;
public function getParentSal(){
return parent::getSal();
}
}
$manager = new Manager();
//子类并且有getsal方法,这个方法是子类继承了父类的getsal方法,但是父类的私有属性$sal并没有被继承,这个被继承的父类getsal方法还是为父类的私有属性$sal服务,而不为子类的$sal服务
echo $manager->getSal();
echo $manager->getParentSal();
//输出结果是 3000 3000
## 例子2.2
//子类将父类的属性重写的情况下
//父类 protected $sal =3000
//子类 protected $sal = 5000
class employee{
protected $sal=3000;
public function getSal(){
return $this->sal ;
}
}
class Manager extends employee {
protected $sal=5000;
public function getParentSal(){
return parent::getSal();
}
}
$manager = new Manager();
echo $manager->getSal();
echo $manager->getParentSal();
//输出结果是 5000 5000
## 三.子类对父类方法重写
//子类重写的方法对当前private有效
class employee{
private $sal=3000;
public function getSal(){
return $this->sal ;
}
}
class Manager extends employee {
private $sal=5000;
//重写父类的方法
public function getSal(){
return $this->sal ; //这里返回的是子类的private属性
}
public function getParentSal(){
//这里返回的是父类的priavte属性
return parent::getSal();
}
}
$manager = new Manager();
echo $manager->getSal();
echo $manager->getParentSal();
//输出结果是 5000 3000
4. static关键字
- static关键字用来修饰属性和方法
- static关键字不经过实例化就能使用,不根据实例的不同而改变
- 静态属性在内存中只有一份,为所有实例共用
- 使用方法是 类名::静态属性 类名::静态方法名 或者 使用self::调用当前类中的其它静态方法
- 静态方法不能调用非静态属性(也就是不能用$this关键字来调用非静态属性,更不能用self:非静态属性这种错误的方式调用)
5. const修饰
- const用来修饰常量,使用方法和静态属性一样 类名::常量名
- 常量不能被修改,修改会报错
- 常量要大写
6. final关键字
final关键字用于类和方法之前,final类不可以被继承,final方法不可以被覆盖(重写)
7. 抽象方法和抽象类
-
abstract修饰一个类和方法
-
抽象类不能被实例化,实例化会报错
-
子类(非抽象类)继承父类(抽象类),这时候子类是可以被实例化的,不会报错
-
抽象类继承抽象类的话,不需要重写其中的抽象方法,但是此时子类仍然不能被实例化
-
抽象类继承抽象类目的是对抽象类进行扩展
-
抽象方法只有声明,没有具体的实现方法
-
抽象方法没有{},而是采用;结束
-
抽象方法在子类中必须被重写,如果不重写就会报错,同时要注意参数的个数.如果父类中没有抽象方法,子类继承的时候不重写也不会报错
-
如果有抽象方法,当前类必须被声明为抽象类(但是抽象类中可以有非抽象方法)
abstract class User{
protexted $sal = 0;
abstract function getSal(); //注意这里没有{}
}
8. 接口的定义和规范
- 接口是一种特殊的抽象类,只包含抽象方法和静态常量,没有其他类型的内容
- 接口的写法 : interface 接口名{}
- 接口抽象方法只能用public修饰,默认也是public权限,即使是final和abstract也不行
- 注意其他抽象方法是用abstract修饰的,这里不用,只需写法一直就可以了
- 接口中的静态常量就是用const修饰的就是了
interface User{
function getName(); //这是个抽象方法,最后是以 ; 结束的
//function getAge(){}; //注意这是个非抽象方法,这样会报错的
}
9. 接口的实现
- 接口实现使用implements
- 一个类可以实现多个接口(解决了php单继承问题)
- 同抽象类的继承一样,实现接口要实现其中的抽象方法,否则会报错
class Student{
protect $grade ;
public function getGrade(){
return $this->grade;
}
}
interface User{
function getName();
}
interface Administrator{
function setBulletin($_bulletin);
}
//可以一次实现多个接口
class Admin implements User,Administrator{
function getName(){}
function setBulletin($_bulletin){}
}
//可以实现继承并且实现多个接口
class Admin extend Student implements User,Administrator{
function getName(){}
function setBulletin($_bulletin){}
}
10. 多态
- 多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性
- 同一个操作作用于不同的类的实例,将产生不同的执行结果。也即不同类的对象收到相同的消息时,将得到不同的结果
11. 接口的作用
- 继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的
- 接口用于描述一组类的公共方法/公共属性.它不实现任何的方法或属性,只是告诉继承它的类《至少》要实现哪些功能,继承它的类可以增加自己的方法.
- 使用接口可以使继承它的类: 命名统一/规范,易于维护
- 提供永远的接口。 当类增加时,现有接口方法能够满足继承类中的大多数方法,没必要重新给新类设计一组方法,也节省了代码,提高了开发效率.
# 下面是一个关于usb接口的例子
//首先定义一个usb接口
interface USB{
public function run();
}
# 下面定义三个不同的类key,mouse,store,都实现了上面的接口
//键盘
class key implements USB{
public function run(){
$this -> init();
}
public function init(){
echo "key running ..";
}
}
//鼠标
class mouse implements USB{
public function run(){
$this -> init();
}
public function init(){
echo "mouse running ...";
}
}
//移动硬盘
class store implements USB{
public function run(){
$this -> initialize();
}
private function initialize(){
echo "store running ..";
}
}
//以上三种设备都要遵循接口的run方法
# 下面实现多态
//1.首先我们可以
$key = new key();
$Key->run();
$mouse = new mouse();
$mouse->run();
//上调用不同的类的相同名方法,会输出不同的东东,也就是说每个类里面的同名方法完成的功能可以是完全不同的
//2.我们可以更进一步,用多态实现其调用
class computer{
public function useUSB($obj){
$obj -> run();
}
}
//实例化computer
$computer = new computer();
//给这个实例传入不同的对象(对象是根据接口实现的)
$computer -> useUSB(new mouse());
$computer -> useUSB(new store());
$computer -> useUSB(new key());
//3.再进一步,此时我们又有个声卡设备,
//如果按照传统的方式,我们需要创建声卡类并实现接口,然后实例化声卡类,调用声卡方法,没增加一种设备,就要多一种调用方法,多了就不容易维护了
//现在我们如果有了上面的方法,只需要创建新的声卡类,然后调用的时候还是使用computer中的useUSB方法,就可以了,这样看起来更容易维护,更容易扩展
12. 对象克隆 __clone()方法
- 在项目中,使用两个或多个一样的对象,重新new关键对象,并且赋予相同的属性,是比较繁琐的
- 使用__clone()方法,可以得到两个一模一样的对象,并且互相不干扰
- __clone方法中有this和that指针
class Person{
var $name;
var $age;
//构造函数,
function __construct($name='',$age=''){
//通过构造函数传参来给类中的属性赋值
$this->name = $name;
$this->age = $age;
}
function say(){
echo "我的名字是".$this->name;
echo ",年龄是".$this->name;
}
function __clone(){
//注意这里的this和that指针,$this指向复本people2,$that指向原本people1
$this->name = "我是假的$that->name";
$this->age = 30;
}
}
$people1 = new Person("张三",20);
$people2 = clone $people1;
$people1->say();
$people2->say();
//结果:
//我的名字是张三,年龄是20
//我的名字是假的张三,年龄格式30
13. call方法
- 当我们调用的方法在对象内容不存在时候,会出错,并停止运行程序
- 我们可以使用call方法来弹出一个提示说此方法不存在,然后程序可以继续执行
class Test{
//调用不存在的方法时候自动调用次方法,第一个参数是方法名,第二个参数是数组参数
public function __call($methodName, $args){
//我们可以在这里写一些处理逻辑
print_r($args);
echo "您传入的方法不存在";
}
}
$test = new Test();
$test->demo("one","two","three",) //因为demo方法并不存在,所以会自动调用上面的__call方法