基本介绍:
面向对象编程又称oop编程,三大特征是: 封装性, 继承, 多态. 说明一下,在php面向对象编程中,多态提的并不是很多,因为php本身就是天生的多态。
抽象的概念:
在面向对象编程中,将一类事物的共有的属性(成员属性)和行为(成员方法)提取出来,形成一个模板(类), 这种解决问题的方法就是抽象。
访问修饰符的介绍:
在php中,提供了三种访问控制符 public , protected 和private。
public 类内部、外部和子类都可以访问;
protected 表示受保护的,只有本类或子类可以访问;
private 表示私有的,只有本类内部可以使用;
强调: 上面的说的访问控制访问,对属性和成员方法都起作用.
案例说明:
class Person{ public $name; protected $job; private $salary; //构造函数 public function __construct($name,$job,$salary){ $this -> name = $name; $this -> job = $job; $this -> salary = $salary; } //三个不同访问修饰符的成员方法 public function getName(){ echo "name是" . $this -> name; } protected function getJob(){ echo "job是" . $this -> job; } private function getSalary(){ echo "salary是" . $this -> salary; } //在类的内部使用protected的属性和方法 public function showJob(){ echo "job是" . $this -> job; $this -> getJob(); } //在类的内部使用private的属性和方法 public function showSalary(){ echo "salary是" . $this -> salary; $this -> getSalary(); }}$p1 = new Person('小明','程序员',13000);//public的属性和成员方法可以在外部直接访问echo $p1 -> name;$p1 -> getName();//protected的属性和方法不能直接在外部访问需要通过在内部创建一个public方法访问$p1 -> showJob();//private的属性和方法不能直接在外部访问需要通过在内部创建一个public方法访问$p1 -> showSalary();
访问protected和private属性的三种形式:
① 使用魔术方法__get 和 __set 来实现对protected 和 private 属性的操作(详情见魔术方法)
(1) 优点: 简单,一对__set 和 __get 就可以搞定所有的private , protected属性
(2) 缺点: 不够灵活,没有办法对各个属性进行控制和验证.
②对每一个private 和 protected 属性提供一对get/set方法, 这样就可以分别控制,各个属性,并进行验证.
案例说明:
//创建一个书类,里面包含书名(bookname)作者(author)价格(price)销量(saleNum)class Book{ public $bookname; public $author; protected $price; private $saleNum; public function __construct($bookname,$author,$price){ $this -> bookname = $bookname; $this -> author = $author; $this -> price = $price; } //给)价格(price)提供一对get和set方法 public function getPrice(){ return $this -> price; } public function setPrice($price){ if(is_numeric($price) && $price > 0.0){ $this -> price = $price; }else{ echo "价格格式异常"; } } //给)销量(saleNum)提供一对get和set方法 public function getSaleNum(){ return $this -> saleNum; } public function setSaleNum($saleNum){ if(is_numeric($saleNum) && $saleNum > 0){ $this -> saleNum = $saleNum; }else{ echo "销量格式异常"; } }}$book1 = new Book('射雕英雄传','金庸',45.50);echo "射雕英雄传的价格是" . $book1 -> getPrice();$book1 -> setPrice(63.00);echo "射雕英雄传的价格是" . $book1 -> getPrice();$book1 -> setSaleNum(500000);echo "射雕英雄传的销量是" . $book1 -> getSaleNum(); //输出结果是: 射雕英雄传的价格是45.5 射雕英雄传的价格是63 射雕英雄传的销量是500000
(1) 优点: 可以对每个属性进行验证,因此很灵活.
(2) 缺点: 会造成有比较多的setXxx 和 getXxx方法,但是这个没有什么大的问题.
(3) 推荐使用这种方法,在实际开发中,这种方式比较多.
③写一个成员方法,可以根据业务逻辑,一次性对多个属性进行批量操作 。
案例说明:
//创建一个类(movie)里面包含名称(name)导演(director)成本(cost)票房(tickeOffice)class Movie{ public $name; public $director; protected $cost; private $ticketOffice; public function __construct($name,$director,$cost){ $this -> name = $name; $this -> director = $director; $this -> cost = $cost; } public function showAllInfo(){ echo '电影的信息如下:'; echo '电影名:' . $this -> name; echo '电影导演:' . $this -> director; echo '电影成本:' . $this -> cost; echo '电影票房:' . $this -> ticketOffice; } //创建一个方法来容纳针对多个属性修改的方法 public function updateInfo($director, $cost, $ticketOffice){ //结合setXxx 来完成 $this->setDirector($director); $this->setCost($cost); $this->setTicketOffice($ticketOffice); } //setXxx GetXxx public function SetDirector($director){ $this->director = $director; } public function getDirector(){ return $this->director; } public function setCost($cost){ //加入数据的验证和判断 if(is_numeric($cost) && $cost > 0.0){ $this->cost = $cost; }else{ echo ' 输入成本格式有问题 '; } } public function getCost(){ return $this->cost; } public function setTicketOffice($ticketOffice){ //加入数据的验证和判断 if(is_numeric($ticketOffice) && $ticketOffice > 0.0){ $this->ticketOffice = $ticketOffice; }else{ echo ' 输入票房格式有问题 '; } } public function getTicketOffice(){ return $this->ticketOffice; }}$movie1 = new Movie('醉拳1','袁和平',2000000);$movie1 -> showAllInfo();$movie1 -> updateInfo('袁小田',2000000,8000000);$movie1 -> showAllInfo(); 输出结果: 电影的信息如下: 电影名:醉拳1 电影导演:袁和平 电影成本:2000000 电影票房: 电影的信息如下: 电影名:醉拳1 电影导演:袁小田 电影成本:2000000 电影票房:8000000
对象运算符的连用:
案例说明:
//对象运算符连用class Student{ public $name; protected $school; public function __construct($name,$school){ $this -> name = $name; $this -> school = $school; } //给$school提供get方法和set方法 public function getSchool(){ return $this -> school; } public function setSchool($school){ $this -> school = $school; }}class School{ public $name; public $address; private $my_class; public function __construct($name,$address,$my_class){ $this -> name = $name; $this -> address = $address; $this -> my_class = $my_class; } //给$my_class提供get方法和set方法 public function getMyClass(){ return $this -> my_class; } public function setMyClass($my_class){ $this -> my_class = $my_class; }}class AtClass{ protected $name; protected $stu_num; private $introduce; public function __construct($name,$stu_num,$introduce){ $this -> name = $name; $this -> stu_num = $stu_num; $this -> introduce = $introduce; } public function __get($pro_name){ return $this -> $pro_name; }}//创建MyClass对象$class1 = new AtClass('建筑设备0931',50,'09年9月入学12年6月毕业属于水利系');//创建School对象$school1 = new School('福建水利电力职业技术学院','福建省永安市',$class1);//创建Student对象$student1 = new Student('刘杰',$school1);//通过$studengt来获取他对应的班级信息echo '' . $student1 -> name . '所在的班级是属于' . $school1 -> name . '的' . $student1 -> getSchool() -> getMyClass() -> name;
输出结果是: 刘杰所在的班级是属于福建水利电力职业技术学院的建筑设备0931
继承:
概念:可以解决代码复用,让编程更加靠近人类思维,当多个类存在相同的属性和方法时可以从这些类中抽象出父类,再父类中定义这些相同的属性和方法所有子类不需要重新定义这些属性和方法只需要通过( 继承class 子类名 extends 父类名{ } )就可以拥有父类定义的方法和属性。
说明:
(1) 继承的根本作用就是解决代码的复用性,减少冗余度 , 同时利用类的维护和扩展
(2) 继承时的关键字是 extends , 这个是固定的,不能修改.
案例说明:
class Person{ public $name; public $age; public $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } public function eat(){ echo "" . $this -> name . '在吃饭'; }}class Man extends Person{ public function drink(){ echo "" . $this -> name . '在喝酒'; }}class Woman extends Person{ public function makeUp(){ echo "" . $this -> name . '在化妆'; }}$man1 = new Man('小明',18,'男');$woman1 = new Woman('小红',19,'女');var_dump($man1,$woman1);$man1 -> eat();$woman1 -> eat();
继承的注意事项:
(1) 子类最多只能继承一个父类(指直接继承)
(2) 子类可以继承其父类(或者基类)的 public ,protected修饰的变量(属性) 和 函数(方法)
(3) 在创建某个子类对象时,默认情况下会自动调用其父类的构造函数(指在子类没有自定义构造函数情况时)
(4) 如果在子类中需要访问其父类的方法(构造方法/成员方法 方法的访问修饰符是public/protected),可以使用父类::方法名(或者 parent::方法名 ) 来完成。
(5) 如果子类(扩展类)中的方法和父类(基类)方法相同,我们称为方法重写,
方法的重载:
说明:
(1) 方法重载不推荐使用, 但是有些项目中也有使用
(2) 面试笔试有人问你.
案例说明:
class Person{ public $name; protected $age; //求和 private function getSum($n1,$n2){ return $n1 + $n2; } //求最大值 private function getMax($n1,$n2,$n3){ return max($n1,$n2,$n3); } //__call 魔术方法 public function __call($method_name,$parameters){ if($method_name == 'getVal'){ if(count($parameters) == 2){ return $this -> getSum($parameters[0],$parameters[1]); }else if(count($parameters) == 3){ return $this -> getMax($parameters[0],$parameters[1],$parameters[2]); } }else{ echo "调用的形式异常"; } }}//传统的oop,方法的重载$p1 = new Person();$sum = $p1 -> getVal(25,19);echo '$sum输出的结果是' . $sum;$max = $p1 -> getVal(19,63,25);echo '$max输出的结果是' . $max;
魔术方法__callStatic:
当我们调用一个不可以访问(protected/private/不存在)的静态方法时,__callStatic魔术方法就会被系统调用。
案例说明:
class A{ public static function __callStatic($method_name,$parameters){ echo '$method_name' . $method_name; } protected static function text(){ echo 'test'; } protected static function text2(){ echo 'test2'; }}A::test();A::test2();A::hello();