4面向对象

[TOC]

面向对象

1. 面向对象的基本概念

1.1 什么是面向对象编程。

准确的说面向对象编程我们叫 OOP.面向对象的编程分为三部分:面向对象分析(Object Oriented Analysis,OOA)、面向对象设计(Object Oriented Design,OOD),以及面向对象编程(Object Oriented Programming)。面向对象编程的两个中个重要的概念是类和对象。

1.2. 类

世间万物皆对象,万事万物皆对象。当然,这是在 js 当中的一个概念。在其他的编程语言当中,我们说时间万物都具有它自身的属性和方法,通过这些属性和方法,可以将不同的事物区分开来,这就是我们在座的面向对象类的抽象。例如,人具有身高。体重和肤色等等这些属性。还可以吃饭,学习走路可以做一些活动。这些活动就是人具有的功能。而前面所说的体重,肤色,身高等等这些是什么呢?是属性。所以我们就可以把人看作是程序当中的一个类。那么人的身高可以看做什么?可以看做类的属性走路啊,吃饭呀,可以看做类的方法。所以什么是类,类是属性和方法的集合.是面向对象编程最核心的东西。也是它的基础。所以通过类呢,我们可以将一些零散的用来去实现某一个功能的代码进行一些管理。比如说,我们可以创建一个运动类。爱运动类里面包括有这么些个属性姓名身高体重年龄。和性别,然后我再定义几个方法,他能踢足球,他能打篮球啊,能举重能跳高。能吃能玩。

1.3. 对象

类只是具备某项功能。一个抽象模型实际应用当中呢,我们需要使用的是对象。所以我们就需要从那当中去实例化出来这个对象,然后去使用这些对象。对象呢,是类进行实例化之后的一个产物。它是一个实体,是一个独立的个体。例如,我们仍然以人为例。"黄种人是人"这句话里边儿。没有错误对吧,但是反过来说 "人是黄种人",就有问题,因为除了黄种人,还有白人,黑人等就,这里的"黄种人"就是"人"这个类中的一个实例对象。

1.4. 面向对象的三大特征

面向对象编程的大大特征就是封装性,继承性,多态性

1.4.1. 封装性

封装性也可称之为信息隐藏,就是把一个类的使用和实现分开,只保留有限的接口(方法)与外部练习。同时也避免程序之间的 相互依赖而产生的不便。

1.4.2. 继承性

继承性就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法。并且我们可以重写和添加新的属性方法。可以简化对象和类的创建,提高代码的可复用性,继承分单继承和多继承。PHP 中支持的是单继承。一个子类有且只有一个父类。

1.4.3. 多态性

同一个类的不同对象,调用一个方法可以获得不同的结果。增强程序的灵活性和重用性。

2. PHP 对象

2.1. 类的定义

和很多其他面向对象的语言一样,PHP 通过 class 关键字加类名来定义类。

<?php
class SportObject{
    // ----
}
?>

2.2. 成员方法

类中的函数被称为成员方法,函数与成员方法唯一的区别就是函数实现的是某个独立的功能。而成员方法实现的是类的一个行为,它是类的其中一部分。
关键字(修饰符) 成员方法

<?php
class SportObject{
    function bealBasketBall($name,$age,$height,$sex){
        echo $name.'<br>';
        echo $age.'<br>';
        echo $height.'<br>';
        // return ;
    }
}
?>

2.3. 类的实例化

首先我们要实例化对象(通过 new 关键字 实例化对象),才能通过对象执行对应的行为方法。通过对象->成员方法 来调用成员方法。

<?php
class SportObject{
    function bealBasketBall($name,$age,$height,$sex){
        if($height>=180){
            return $name.'符合打篮球的身体素质要求!';
        }else{
            return $name.'不符合打篮球的身体素质要求!';
        }
    }
}
$s1=new SportObject();
echo $s1->bealBasketBall('曾辉',20,170,'男');
$s2=new SportObject();
echo $s1->bealBasketBall('曾辉2号',40,181,'男');
?>

2.4. 成员变量

类中的变量,也称为成员变量。有些人也把它叫做属性或者字段。成员变量的是用来保存数据信息。或者与成员方法进行一些交互来实现某项功能。
定义成员变量和成员方法:
关键字(修饰符) 成员变量名

关键字可以使用public ,private, protected, static 中的任意一个。

访问成员变量和成员方法的方法一样,对象->成员变量

class SportObject{
    // 声明成员变量。
    public $name;
    public $height;
    public $sex;
    public function boolFootBall($name,$height,$sex){
            return $name.'是个足球运动员';
    }
}
$s1=new SportObject;
$s1->name='佚名';
var_dump($s1);
// $s1->boolFootBall('佚名');

<table> <tr><td bgColor="orange"><strong>注: this-> 所用是调用本类中的 成员变量或成员方法。 无论使用的是"this->" 还是"对象名->"哪种格式,后面的变量名是没有$符号的.
</strong></td></tr></table>

2.5. 类常量

常量是在程序运行期间,不可改变的量,我们说他是一个恒值,举例圆周率就是一个常量。定义常量,我们使用关键字 const。

class SportObject{
    const SPORT_TYPE="体育运动";
    public $name;
    function setName($name){
        $this->name=$name;
    }
    function getName(){
        return $this->name;
    }
}
$s1=new SportObject;
$s1->setName('aaa');
echo $s1->getName().'<br>';
echo $s1->name.'<br>';
echo SportObject::SPORT_TYPE.'通过类::常量名';

2.6 构造函数和析构函数

2.6.1 构造函数

当一个类实例化为一个对象的时候,可能可能会随着对象的初始化而初始化一些成员变量。就是给一些成员变量复制值。这种情况下我们就可以使用构造函数。因为咱对象实例化过程当中构造函数是自动执行的。

class Person{
    public $name;
    public $age;
    public $sex;
    public $height;
    // 我们可以通过"__construct()"
    public function __construct(){
        echo '123';
    }
}

$p1=new Person;
// 如果成员变量过多,写起来比较麻烦
// $p1->name='aa';

构造函数是在初始化对象时使用的,如果类中没有构造方法,PHP 会自动生成一个构造函数,自动生成的构造方法是没有参数的。

2.6.2 析构函数

析构函数的作用和构造方法方法刚好相反,是对象被销毁时被调用的,作用呢是释放内存。

<?php
class Person{
    public $name;
    public $age;
    public $sex;
    public $height;
    // 我们可以通过"__construct()"
    // 构造函数
    public function __construct($name,$height,$age,$sex){
        // 为成员变量赋值。
        $this->name=$name;
        $this->height=$height;
        $this->age=$age;
        $this->sex=$sex;
        echo $this->sayHi();
    }
    public function sayHi(){
        return "你好,我叫$this->name ,我今年$this->age 岁了,身高$this->height,性别$this->sex";
    }
    // 析构函数
    public function __destruct(){
        echo '已经被释放掉了';
    }
}
$p2=new Person("佚名",180,23,'女');

2.7 继承和多态

其实继承和多态啊最根本的作用就是完成代码的重用。

2.7.1 继承

子类继承父类的所有成员变量方法,包括构造方法,当子类被实例化的时候,PHP 会先在子类当中找构造方法,如果子类已经有自己的构造方法。PHP 会先调用子类的方法。当子类当中没有的时候,PHP 才会去调用。父类当中的构造方法,这就是继承。

// 父类(基类)
class SportClass{
    // 定义成员变量
    public $name;//姓名
    public $age;//年龄
    public $weight;//体重
    public $sex;//性别
    public function __construct($name,$age,$weight,$sex){
        $this->name=$name;
        $this->age=$age;
        $this->weight=$weight;
        $this->sex=$sex;
    }
    function sayHi(){
        echo '你好,我是'.$this->name;
    }
}

/**子类(派生类)BealBasketBall*/
class BealBasketBall extends SportClass{//定义子类,继承父类
    // 定义成员变量  身高
    public $height;
    public function __construct($name,$height){
        $this->height=$height;
        $this->name=$name;
    }  
    
    // function sayHi(){
    //     echo '你好,我是'.$this->name;
    // }
}

$b1=new BealBasketBall('曾辉',198);

2.7.2 多态

多态好比有一个成员,方法是让大家去游泳,这时有人带着游泳圈还有人拿着浮板。还有人什么也不带。虽然是同一种方法,但是却产生了不同的形态,这就叫多态。

多态存在两种形式,覆盖和重载。
1).所谓的覆盖,在子类中重写父类的方法。而在子类的对象当中,虽然调用的是父类当中相同的方法,但返回的结果是不一样的。你看啊,上面的那个例子当中都调用了父类当中的说明方法。但是返回的结果却不同。
2).再就是重载,重载是类的多态的另外一种体现。函数在重载的时候会有一个标识符。被当做多个函数名称。而且呢,能够通过函数的参数的个数或者参数的类型,将这些同名的函数区分开来,(方法名称是相同的),可能是参数的数量或者参数的类型不同。以便于去使用和调用的时候不发生混淆。
PHP所提供的重载(overloading)是指动态地创建类属性和方法。我们是通过魔术方法(magic methods)来实现的。

class A{
    function __call($name,$num){
        echo "方法名称:".$name.'<br>';
        echo '参数存在的个数:'.count($num).'<br>';
        if(count($num)==1){
            echo $this->list1();
        }
        if(count($num)==2){
            echo $this->list2();
        }
    }

    public function list1($a){
        return "这是list1函数,:参数:$a";
    }
    public function list2($a,$b){
        return "这是list1函数,:参数1:$a ,参数2:$b ";
    }
}

$a=new A;
$a->list(1);

2.8 "$this->" 和"::"的使用

PHP通过为变量"this->"和作用域操作符"::"来实现访问自己的成员变量和成员方法的。 **1.this->**
在本类内部我们可以通过"this" 访问当前类实例化的对象。调用方法或成员变量的话,则使用"this->成员变量"||"this->成员方法" 来访问成员方法和变量。所以"this->"只在类的内部使用

class Demo{
    function exam(){
        if(isset($this)){
            echo '$this的值:'.get_class($this);
        }else{
            echo '$this 未定义';
        }
    }
}
$d1=new Demo;
$d1->exam();

2. 操作符::
$this只能在类的内部去使用。操作符"::"可以在没有声明任何实例的情况下,访问类当中的成员方法或成员变量。

关键字::变量名/常量名/方法名

关键字有三种情况:

  • parent: 可以调用父类中的 成员变量,成员方法和常量
  • self:可以调用当前类中的 静态成员和常量
  • 类名:可以调用本类中的静态变量,常量和静态方法
class A{
    const NAME_='A';
    public $name;
    public $age;
    public $sex;
    public function __construct($name,$age,$sex){
        $this->name=$name;
        $this->age=$age;
        $this->sex=$sex;
    }
}

class B extends A{
    const NAME_='B';
    public $height;
    public $weight;
    public function __construct($name,$age,$sex,$height,$weight){
        parent::__construct($name,$age,$sex);  
        $this->height=$height;
        $this->weight=$weight;
    }
    public function a(){
        self::NAME_;
        parent::NAME_;
    }
}
$b1=new B('姓名','年龄','xingbie','身高','体重');
B::NAME_;

2.9 修饰符

public、private、protected、static和final。这些关键字是用来限定类成员(包括方法和变量)的访问权限。

2.9.1 public(公共成员)

顾名思义就是可以公开的,没有必要去隐藏的一些数据信息。可以用public来去修饰当前的成员方法或者成员变量。它可以在程序的任何位置出现(类的内部,类的外部)。可以被其他的类和对象去调用。子类呢可以继承和使用父类当中所有的,公共成员。

class Person{
    public $name="李雷";
    public function fn(){
        // 1.可以在类的内部访问,对当前类的 内部可见
        echo $this->name;
    }
}

class Students extends Person{
    public function fn1(){
        // 2.可以在子类的内部访问,对子类的内部可见
        echo $this->name;   
        $this->fn();
    }
}
// 3.在类的外部可见
$s1=new Person();
$s1->fn();
$s2=new Students();
$s2->fn();
$s2->fn1();

2.9.2 private(私有成员)

被private关键字所修饰的成员方法和变量,只能在所属类的内部被调用和修改,不可以在类外部访问,在子类中也不可以。

<?php
class Book{
    private $name='HTML';
    public function setName($name){
        // 1.在当前类内部 可访问
        $this->name=$name;
    }
    public function getName(){
        echo $this->name;
    }
    private function c1(){
        echo '123';
    }
}

class Histoty extends Book{
    public function getBookName(){
        // 2.在子类内部不可见 不可访问继承来的父类中的私有成员变量 私有方法
        echo $this->name;
        $this->c1();
    }
}
// $b1=new Book;
// $b1->setName('PHP');
// $b1->getName();
// 3.在类的外部不可访问 私有成员变量或私有成员方法
// $b1->name='js';
// $b1->c1();

$h1=new Histoty();
$h1->getBookName();

对于成员方法和成员变量,如果没有指定关键字,那就默认是public。

2.9.3 protected(保护成员)

被protected 修饰的类成员,可以在当前类和子类中被调用。去其他地方则不可以访问。

class Person{
    protected $money=10;
    public function fn(){
        echo $this->money;
        // 1.在当前的内部可以访问
    }
}
class Stu extends Person{
    public function fn1(){
        echo $this->money;
        // 2. 可以在子类的内部访问
    }
}
// 3. 在类的外部不能直接访问,
$p1=new Person;
$p1->fn();
// echo $p1->money;
$s1=new Stu;
$s1->fn1();

2.10 静态成员(变量,方法)

不是所有的方法都要通过创建对象来去调用的,我们可以。通过给变量或者方法加上static关键字来直接调用。也叫做访问静态成员。

关键字::静态成员

关键字可以有两种:

  • self,在类的内部调用静态成员是使用。
  • 静态成员所在的类名,在类的外部调用类内部的静态成员时所使用。
    在静态方法当中只能调用静态变量,而不能调用普通的变量。而普通方法里面可以调用静态变量。
    使用静态成员,除了可以不需要实例化对象外,另一个作用就是在对象被销毁后,仍然保留被修改的静态数据,以便于下次继续使用。
class Book{
    static $num=0;//声明一个静态变量$num,初始值为0;
    public function showMe(){
        echo '您是第'.self::$num.'位访客';
        self::$num++;//
    }
}
$b1=new Book();
$b1->showMe();
$b2=new Book();
$b2->showMe();
echo '一共有'.Book::$num.'位访客';

2.11 final 关键字

被final修饰过的类和方法就是"最终的版本",如果类被final修饰过,该类不可以再被继承,也不能再有子类。

final class Book{
    public $name='';
    public function __construct($name){
        $this->name=$name;
    }
}
class Histoty extends Book{
    public $height='';   
}
//结果: Fatal error: Class Histoty may not inherit from final class (Book)

如果方法被final修饰过,方法在子类中不可以进行重写,也不可能被覆盖。


class Book{
    public $name='';
    public function __construct($name){
        $this->name=$name;
    }
    final public function getName(){
        echo $this->name;
    }
}
class Histoty extends Book{
    public $height='';   
    public function  getName(){
        echo '123';
    }
}
//结果:Fatal error: Cannot override final method Book::getName() in
 

2.12 对象类型检测

instanceof操作符可以检测当前对象是属于哪一个类。

ObjectName instanceof ClassName
class Book{
    public $name='';
    public function __construct($name='佚名'){
        $this->name=$name;
    }
}
class History{

}
$a=new Book;
$b=new History;
// var_dump($a instanceof Book);//true
var_dump($b instanceof Book);//false

3.魔术方法(__)

3.1 __get和__set() 方法

这两个魔术方法的作用分别是:

  • 当程序试图去写入一个不存在或者不可见的成员变量的时候PHP就会执行__set()方法。__set()方法呢,包括有两个参数,分别是变量名称和变量的值,这两个参数不可省略。

  • 当程序调用一个未定义或者不可见的成员变量的时候,可以通过__get()方法来去读取变量的值.__get()这个方法有一个参数表示你要调用的这个变量名称。

<?php
class SportClass{
    public $height='1231';
    private $type='21312';
    public function __get($name){
        if(isset($this->$name)){//判断变量是否被声明
            echo '变量'.$name.'值:'.$this->$name.'<br>';
        }else{
            echo '变量'.$name.'未定义';
            $this->$name=0;
            echo $this->$name;
        }
    }
    public function __set($name,$value){
        if(isset($this->$name)){
            echo '私有成员';
            echo '变量'.$name.'赋值:'.$value.'<br>';
        }else{
            $this->$name=$value;
            echo '变量不存在';
        }
    }
}
$b=new SportClass();
// echo $b->type;
// echo $b->sex;
// $b->type='213';
$b->sex=234;
echo $b->sex;

3.2 __tostring()方法

当使用echo或print输出对象时,将对象转化为字符串。

class SportClass{
    private $type='21312';
    public function __tostring(){
        return $this->type;
    }
}
$b=new SportClass;
echo $b;

3.3 __autoload()方法

尝试加载未定义的类是,触发__autoload()方法,__autoload()接受一个参数,参数是类的名称。

function __autoload($classname){
    $class_path=lcfirst($classname).'Class.php';
    if(file_exists($class_path)){
        include_once($class_path);
    }
}


$b=new BaseFile;
var_dump($b);
$c=new Base();
var_dump($c);

3.4 中文字符串截取类

在Php当中啊!我们经常要去对字符串进行一些截取。如果是英文字符串的话,我们可以直接使用substr()函数来去完成。但是当出现中文字符串的时候,如果你依然使用这个substr()函数,就有可能会出现乱码的情况。因为一个汉字是由两个字节组成的。所以当截取的字符如果出现奇数的时候,就有可能将一个汉字给拆分开来。从而导致输出一个不完整的汉字,显示出来就是乱码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容