面向对象编程基础

一、什么是面向对象?

面向对象编程(Object Oriented Programming),简称OOP。

它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。

面向对象的特性:

  1. 封装性
  2. 继承性
  3. 抽象(多态性)

二、类的声明与实例化

在声明一个类时,使用class关键字,声明这个类的与这个类所在的文件最好同名。

  • 以下是声明了一个Student类:
  1. class Student {
  2. // 在这里面声明成员属性和方法
  3. }

类的属性和方法有三种:

  1. public: 公开的,外部可以访问的;
  2. protected: 受保护的,仅限本类和子类访问;
  3. private: 私有,仅限本类使用,外部和子类无法访问。

以下是声明了一个Student类,以及类中的属性和方法的案例。

  1. class Student
  2. {
  3. // 属性:变量
  4. // 公有属性,外部、本类和子类可以访问
  5. public $name;
  6. // 受保护成员,仅限本类以及子类访问
  7. protected $gender;
  8. // private: 私有成员,仅限本类中的使用
  9. private $age;
  10. private static $score;
  11. // 构造函数
  12. // __construct()属于魔术方法,由系统自动调用
  13. // 在类的实例化过程中会调用它
  14. public function __construct($name, $gender, $age)
  15. {
  16. $this->name = $name;
  17. $this->gender = $gender;
  18. $this->age = $age;
  19. }
  20. // 方法
  21. public function getStuInfo() {
  22. return "姓名:{$this->name},性别:{$this->gender},年龄:{$this->age}岁。";
  23. }
  24. }

实例化Student类:

  1. $stu = new Student('张三', '男', 16);
  2. echo $stu->getStuInfo();

访问类中的公有属性:

  1. echo $stu->name; // 张三

三、静态方法和成员(static)

当一个类的成员或方法被声明成了静态(static),那么,就无法通过类实例去访问了,必须使用类直接调用。

  1. class Staff {
  2. public $name;
  3. // 静态成员
  4. public static $salary;
  5. // 构造函数
  6. public function __construct(string $name, int $salary)
  7. {
  8. $this->name = $name;
  9. // 静态成员与类实例无关,因此不能用$this访问,直接使用类去调用
  10. self::$salary = $salary;
  11. }
  12. public static function staffSalary() {
  13. return '员工的工资:'.self::$salary;
  14. }
  15. }

实例化Staff类:

  1. $staff = new Staff('张三', 8899);
  2. // 使用类名访问静态属性
  3. echo Staff::$salary; // 8899
  4. // 使用类名访问静态方法
  5. echo Staff::staffSalary(); // 员工的工资:8899

四、类的继承(extends)

类的继承使用extends关键字,也就是对类的功能进行扩展。

  1. require 'Student.php';
  2. class Sub extends Student {
  3. // 类的继承一般有两个用处:
  4. // 1. 对父类方法进行重写;
  5. // 2. 对父类功能进行扩展。
  6. // 扩展一个属性,score:分数
  7. private $score;
  8. // 子类构造器,重写了父类的方法
  9. public function __construct($name, $gender, $age, $score)
  10. {
  11. // 调用父类成员
  12. parent::__construct($name, $gender, $age);
  13. $this->score = $score;
  14. }
  15. // 重写父类的getStuInfo()方法
  16. public function getStuInfo()
  17. {
  18. return parent::getStuInfo()."分数:{$this->score}";
  19. }
  20. // 增加一个新方法,判断学生成绩是否及格。
  21. public function isPass()
  22. {
  23. if ($this->score > 60) {
  24. return "该学生成绩已及格,分数为:{$this->score}";
  25. }
  26. }
  27. }
  28. $sub = new Sub('张三', '男', 16, 90);
  29. echo $sub->getStuInfo(); // 姓名:张三,性别:男,年龄:16岁。分数:90
  30. echo "<br>";
  31. echo $sub->isPass(); // 该学生成绩已及格,分数为:90

姓名:张三,性别:男,年龄:16岁。分数:90

该学生成绩已及格,分数为:90

五、Trait(代码复用)

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,为了使开发者能复用某些方法。
可以把trait理解为一个公共方法集,它借用了class语法实现了一个轻量级的“类”,但它不是类,所以不能实例化。

  • trait 示例
  1. trait userInfo {
  2. public function getUserInfo () {
  3. return "This is userInfo " . $this->name;
  4. }
  5. }
  6. class User
  7. {
  8. // 使用关键字use引入需要使用的trait
  9. use userInfo;
  10. }
  • 优先级
  1. trait userInfo {
  2. public function getUserInfo () {
  3. return "This is userInfo " . $this->name;
  4. }
  5. }
  6. class UserBase
  7. {
  8. public $username;
  9. // 引用trait
  10. use userInfo;
  11. public function __construct($username)
  12. {
  13. $this->username = $username;
  14. }
  15. public function getUserInfo () {
  16. return "This is UserBase " . $this->name;
  17. }
  18. public function getUserName() {
  19. return "UserBase:".$this->username;
  20. }
  21. }

trait冲突解决办法

当我同时声明了两个trait中有两个相同的方法getUserInfo(),那么在类中访问的时候回报错,具体案例如下:

  1. trait user1 {
  2. public function getUserInfo () {
  3. return "This is user1 ";
  4. }
  5. }
  6. trait user2 {
  7. public function getUserInfo () {
  8. return "This is user2 ";
  9. }
  10. }
  11. class User {
  12. use user1;
  13. use user2;
  14. }

解决办法是:优先级与别名:

  1. trait user1 {
  2. public function getUserInfo () {
  3. return "This is user1 ";
  4. }
  5. }
  6. trait user2 {
  7. public function getUserInfo () {
  8. return "This is user2 ";
  9. }
  10. }
  11. class User {
  12. use user1, user2 {
  13. // 1.优先级
  14. user1::getUserInfo insteadof user2;
  15. // 2.别名
  16. user2::getUserInfo as user2GetUserInfo;
  17. }
  18. }
  19. echo (new User('张三'))->getUserInfo(); // This is user1
  20. echo (new User('张三'))->user2GetUserInfo(); // This is user2

当父类trait与当前子类中存在同名成员时,如何解决?

  1. class SubUser extends User
  2. {
  3. use user3;
  4. public function fun () {
  5. return __METHOD__;
  6. }
  7. }

此时的结果是:SubUser::fun,说明子类的优先级高于父类的。

如果在父类与子类之间加了一个trait里面的一个同名函数,此时的优先级是什么样呢?

  1. trait user3{
  2. public function fun () {
  3. return __METHOD__;
  4. }
  5. }
  6. class SubUser extends User
  7. {
  8. use user3;
  9. public function fun () {
  10. return __METHOD__;
  11. }
  12. }
  13. echo (new SubUser())->fun(); // SubUser::fun

如果此时子类SubUser中没有fun方法呢?

  1. trait user3{
  2. public function fun () {
  3. return __METHOD__;
  4. }
  5. }
  6. class SubUser extends User
  7. {
  8. use user3;
  9. }
  10. echo (new SubUser())->fun(); // user3::fun

此时的结果是:user3::fun

这时,我们可以得出这个优先级的结果:自己拥有的 > trait > 父类的。

更多相关文章

  1. MySQL 5.7.9 服务无法启动-“NET HELPMSG 3534”的解决方法
  2. ES6 变量声明,箭头函数,数组方法,解构赋值,JSON,类与继承,模块化练习
  3. 浅谈Java中Collections.sort对List排序的两种方法
  4. Python list sort方法的具体使用
  5. python list.sort()根据多个关键字排序的方法实现
  6. android上一些方法的区别和用法的注意事项
  7. android实现字体闪烁动画的方法
  8. Android中dispatchDraw分析
  9. Android四大基本组件介绍与生命周期

随机推荐

  1. android WebView总结
  2. DroidDraw Android 界面设计工具使用
  3. Android(安卓)EditText 不弹出输入法总结
  4. 改变Android(安卓)对话框位置及边框
  5. Android(安卓)OS —— 常用fastboot命令
  6. Android程序实现全屏代码
  7. android开发学习笔记(1)我的第一个android
  8. The connection to adb is down, and a s
  9. Android入门教程(二十七)------之Style与
  10. Android控件之ProgressBar