美文网首页程序员
【转载】面向对象、类、接口- 不错的总结

【转载】面向对象、类、接口- 不错的总结

作者: 老夫不才 | 来源:发表于2018-02-12 09:57 被阅读0次

    // 三大特性
    封装:隐藏内部是吸纳,仅开发接口。
    继承:一个对象的成员被另一个对象所使用。语法上体现为代码的共用。
    多态:多种形态。

    /* 【类和对象】 */

    成员:

    类成员:类常量、静态属性、静态方法
    对象成员:非静态属性、非静态方法
    # 除此外,类不能包含任何其他东西!!!
    

    类名、方法名、属性名均不区分大小写

    $this代表本对象,self代表本类,parent代表父类

    类和函数均可被事先编译(仅作为最外层时)

    类的定义必须在单一的PHP区块内,不能被多个PHP标签分割

    // 构造方法

    • 具有构造函数的类会在每次创建新对象时先调用此方法
      void __construct([ mixed $args [, $... ]] )
    • 构造方法所需参数由new实例化对象时,给类增加参数值。
    • 构造方法也可以被手动调用。
    • 5.3.3版本以前,支持于类名同名的方法作为构造方法。
    • 两种冲突时,__construct 优先

    // 析构方法

    • 析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
      void __destruct( void )

    作用:释放对象所占用的资源

    调用的时机

    - 脚本结束时所有资源均被释放,包括对象
    - 手动删除对象时
    - 保存对象的变量被赋予新值时(任何值,包括null)
    - 在使用exit()终止脚本运行时也会被调用
    

    // 静态成员(static关键字)
    - 声明类成员或方法为static,就可以不实例化类而直接访问。
    - 静态成员(属性或方法)均属于类,故不能通过$this或->访问。
    - 静态成员是所有对象共享,属于类。
    - 静态成员用类调用,非静态成员用对象调用。

    静态属性

    - 静态属性不可以由对象通过->操作符来访问。
    - 静态属性只能被初始化为一个字符值或一个常量,不能使用表达式。 所以你可以把静态属性初始化为整型或数组,但不能指向另一个变量或函数返回值,也不能指向一个对象。
    

    静态方法

    - 由于静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用。
    - 用::方式调用一个非静态方法会导致一个E_STRICT级别的错误。
    

    // 访问解析操作符(::)
    - 可以用于访问静态成员、方法和常量,还可以用于覆盖类中的成员和方法。
    - 当在类的外部访问这些静态成员、方法和常量时,必须使用类的名字。
    - self 和 parent 这两个特殊的关键字是用于在类的内部对成员或方法进行访问的。

    // 访问辨析

    • 对象成员,内部通过$this指定,外部通过对象名指定,均用->访问,访问属性时不需加$。
      对象名->属性名 对象名->方法名() $this->属性名 $this->方法名()
    • 类成员,内部通过self或parent指定,外部通过类名指定,均用::访问,访问属性时需加$。
      类名::$属性名 类名::方法名() self::$属性名 self::方法名()
    • 特殊:也可以通过对象访问类成员。(不建议)
      对象名::$类属性名 $this::$类属性名 对象名::$类方法名() $this::类方法名()

    对象成员访问用->,类成员访问用::

    • 无论是静态方法还是非静态方法,均可通过类或对象进行访问。
    • 静态属性通过类访问,静态方法通过对象访问。
    • 只有使用对象调用非静态方法时,$this才可以使用!
    • 静态方法不可使用$this。
    • 类可以调用对象方法,但注意方法内不能有$this。
    • 非静态方法可以调用静态属性或静态方法,反之不可以。

    // 类常量

    • 常量的值将始终保持不变。
    • 在定义和使用常量的时候不需要使用$符号。
    • 常量的值必须是一个定值,不能是变量,类属性或其它操作(如函数调用)的结果。

    定义:const 常量名 = 常量值;

    • 不需要加public等访问修饰限定符
    • 类常量属于类,使用类访问,类名::类常量 或 self::类常量

    // 自动加载对象

    • 在试图使用尚未被定义的类时自动调用 __autoload 函数
    • 自动加载使用到的类名文件(根据类名找相应名称的文件,故需类名与类文件名一致)
    • 每个需要加载类的文件都需要存在__autoload函数
    • 将__autoload函数写入单独的文件,每个需要用到类的文件再require该函数文件
    • __autoload 参数是类名
      function __autoload($class_name) {
      require_once $_SERVER["DOCUMENT_ROOT"] . "/class/$class_name.php";
      }
      // $_SERVER["DOCUMENT_ROOT"] 当前运行脚本所在的文档根目录
    • 可以通过类名,来推导出类所在的文件名!
    • 如果一个项目存在多个自动加载函数时,定义一个可以完成加载的普通函数,并在函数之前使用spl_autoload_register注册该函数。

    spl_autoload_register

    • 注册__autoload()函数
      bool spl_autoload_register ([ callback $autoload_function ] )
    • 可以注册多个自动加载函数,先注册的先执行
    • 一旦注册自动加载函数,__autoload就失效。
    • 注册函数时,参数为函数名(注意加引号);注册方法时,参数为数组

    注册类或对象的方法为自动加载方法时,参数需为数组:

    spl_autoload_register(array(CLASS, '__autoload'));
    CLASS表示当前类名,若是对象可用$this,详细见手册

    对象序列化

    • 只能序列化对象内部的数据,即非静态属性。

    需在反序列化对象之前加载类,也可以触发自动加载机制。

    __sleep 序列化需序列化的属性。
    - 提交未提交的数据,或类似的清理操作,部分串行化对象。
    - 返回一个包含对象中所有应被序列化的变量名称的数组
    __wakeup 反序列化时,预先准备对象需要的资源
    - 重新建立数据库连接,或执行其它初始化操作
    public function __sleep() {
    return array('server', 'username', 'password', 'db');
    }
    public function __wakeup() {
    $this->connect();
    }

    // 对象继承
    class 子类名 extends 父类 {}
    如果一个对象是子类的对象,那么同时也是父类的对象。
    单继承:一个类只能继承一个父类,不能同时继承多个类。但一个父类可以被多个子类继承。

    instanceof 判断某对象是否为某类的对象
    对象名 instanceof 类名

    // 访问控制
    public 公有的(继承链、本类、外部均可访问)
    protected 保护的(仅继承链、本类可访问)
    private 私有的(仅本类可访问)
    根据成员定义位置、访问位置判断。

    兼容性问题

    • 声明属性时,var关键字声明的默认为public权限
    • 声明方法时,省略访问修饰符,默认为public权限

    // 重写 override
    $this代表本对象,被谁调用,就代表哪个对象。

    • 继承时,子类成员名于父类成员名发生冲突,则子类成员会重写父类成员。
    • 属性和方法均可被子类重写。
    • 当父类的方法或属性已经不满足子类的需求,则需要重写。
    • 也可能因为命名不规范导致重写。

    私有属性不能被重写,每个私有属性都会被记录。在记录属性名的同时,还会记录类。

    如果有内置函数被重写,则可调用父类方法。如调用父类构造方法parent::__construct()

    重写限制

    访问限制:
    子类的成员的访问控制必须相等或弱于父类。
    方法参数限制:
    参数数量必须相同,参数名可不同。

    $this确定原则

    $this为调用该方法的对象,表示该方法的执行环境对象。
    - 对象调用
    - 环境的传递。如果当前调用时,不能确定$this的值(静态调用),此时静态调用所处对象环境会传递到被调用的方法内。
    $this并非永远代表本对象,而是由方法的执行环境决定。

    抽象类

    关键字:abstract
    抽象类不能直接被实例化,必须先继承该抽象类,然后再实例化子类。
    抽象类中至少要包含一个抽象方法。非抽象类不能包含抽象方法。
    如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。抽象方法不能包含大括号及方法体。
    继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法。
    即,子类必须重写抽象父类中的所有抽象方法。
    另外,这些方法的可见性必须和抽象类中一样(或者更为宽松)。
    即,如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不能定义为private。

    • 抽象类的子类中的普通方法执行方式和其他类相同。
    • 作用:
      1. 继承,为扩展类,统一公共操作。
      2. 限制结构(规范)。规范子类的结构。

    final

    如果父类中的方法被声明为final,则子类无法覆盖(重写)该方法。
    如果一个类被声明为final,则不能被继承。
    但加有final关键字的类依旧能被实例化!
    // 静态延迟绑定self::,代表本类(当前代码所在类) 永远代表本类,因为在类编译时已经被确定。 即,子类调用父类方法,self却不代表调用的子类。static::,代表本类(调用该方法的类) 用于在继承范围内引用静态调用的类。 运行时,才确定代表的类。 static::不再被解析为定义当前方法所在的类,而是在实际运行时计算的。// 对象的遍历(迭代)- 对象通过属性保存数据,故遍历对象的属性。- foreach语言结构,获得属性名和属性值。 foreach ($obj as $p_name => $p_value) {}# 自定义遍历(迭代器Iterator)Iterator - 可在内部迭代自己的外部迭代器或类的接口Iterator::current — 返回当前元素Iterator::key — 返回当前元素的键Iterator::next — 向前移动到下一个元素Iterator::rewind — 返回到迭代器的第一个元素Iterator::valid — 检查当前位置是否有效# 对象的克隆//对象之间的传值是[引用]传递。克隆:新对象 = clone 旧对象 - 所有的引用属性仍然会是一个指向原来的变量的引用。 __clone()方法在对象被克隆时自动调用。注意:构造方法对应实例化(new),克隆方法对应克隆(clone)。// 单例模式#三私一公单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。# 防止一个类被实例化多次class MySQLDB { private static $instance = null; // 存类实例在此属性中 // 构造方法声明为private,防止直接创建对象 private function __construct() {} public static function getInstance() { if(! self::$instance instanceof static) { self::$instance = new static; } return self::$instance; } private function __clone() {} // 阻止用户复制对象实例}# 重载 overload指动态地"创建"类属性和方法用户可以自由的为对象添加额外的属性,该特性就是重载。所有的重载方法都必须被声明为public。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。重载相关魔术方法的参数都不能通过引用传递。

    属性重载

    • 处理不可访问的属性
      属性重载只能在对象中进行。

    属性重载对于静态属性无效

    在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被声明为static。
    __set 在给不可访问的属性赋值时
    public void __set(string $name, mixed $value)
    作用:批量管理私有属性,间接保护对象结构
    __get 读取不可访问的属性的值时
    public mixed __get(string $name)
    __isset 当对不可访问的属性调用isset()或empty()时
    public bool __isset(string $name)
    __unset 当对不可访问的属性调用unset()时
    public void __unset(string $name)

    方法重载

    • 处理不可访问的方法
      __call 当调用一个不可访问的非静态方法(如未定义,或者不可见)时自动被调用
      public mixed __call(string $name, array $arguments)
      __callStatic 当在调用一个不可访问的静态方法(如未定义,或者不可见)时自动被调用
      public static mixed __callStatic(string $name, array $arguments)

    $name参数是要调用的方法名称。$arguments参数是一个数组,包含着要传递给方法的参数。

    // 类型约束
    函数的参数可以指定只能为对象或数组
    限定为对象则在形参前加类名,限定为数组则在形参前加array
    类型约束允许NULL值
    类型约束不只是用在类的成员方法里,也能使用在函数里。

    // 类与对象·关键字
    this 代表本对象
    public 公有的(继承链、本类、外部均可访问)
    protected 保护的(仅继承链、本类可访问)
    private 私有的(仅本类可访问)
    parent:: 代表父类
    self:: 代表本类(当前代码所在类)
    static:: 代表本类(调用该方法的类)
    static 静态成员(属性、方法),所有对象均可使用,外部也可直接使用或修改,静态方法不可访问非静态成员
    final 方法用final不可被子类重载,类用final不可被继承(方法、类)
    const 类常量(属性)
    abstract 抽象类
    interface 接口
    extends 类继承(子接口继承接口、其他普通类继承)
    implements 接口实现(类实现接口、抽象类实现借口)(对接口的实现和继承均可有多个)
    Iterator 内置接口(迭代)
    clone 克隆
    instance 实例
    instanceof 某对象是否属于某类

    /* 【类与对象相关函数】 */
    class_alias([$original [,$alias]]) 给类取别名
    class_exists($class [,$autoload]) 检查类是否已定义
    interface_exists($interface [,$autoload]) 检查接口是否已被定义
    method_exists($obj, $method)检查类的方法是否存在
    property_exists($class, $property) 检查对象或类是否具有该属性
    get_declared_classes(void) 返回由已定义类的名字所组成的数组
    get_declared_interfaces(void) 返回一个数组包含所有已声明的接口
    get_class([$obj]) 返回对象的类名
    get_parent_class([$obj]) 返回对象或类的父类名
    get_class_methods($class) 返回由类的方法名组成的数组
    get_object_vars($obj) 返回由对象属性组成的关联数组
    get_class_vars($class) 返回由类的默认属性组成的数组
    is_a($obj, $class) 如果对象属于该类或该类是此对象的父类则返回TRUE
    is_subclass_of($obj, $class) 如果此对象是该类的子类,则返回TRUE
    get_object_vars($obj) 返回由对象属性组成的关联数组

    // 魔术方法
    __construct 构造方法
    __destruct 析构方法
    __clone 克隆对象
    __sleep 序列化对象
    __wakeup 反序列化对象
    __autoload 自动加载,使用类但未找到时

    __toString 对象被当作字符串使用时
    __invoke 当尝试以调用函数的方式调用一个对象时
    // 常用类# PHP手册 -> 预定义类Closure 闭包类,匿名函数对象的final类stdClass 标准类,通常用于对象类保存集合数据__PHP_Incomplete_Class 不完整类,当只有对象而没有找到类时,则该对象被认为是该类的对象Exception 异常类PDO 数据对象类// 魔术常量DIR 文件所在的目录LINE 文件中的当前行号 FILE 文件的完整路径(绝对路径)和文件名CLASS 类的名称METHOD 类的方法名,包含类名和方法名FUNCTION 函数名称,用在方法内只表示方法名// 反射机制 Reflection作用:1. 获取结构信息 2. 代理执行ReflectionClass 报告一个类的有关信息ReflectionMethod 报告一个方法的有关信息ReflectionClass::export 输出类结构报告# 代理执行实例化 ReflectionFunction 类的对象 $f = new ReflectionFunction('func'); // func为函数func($p) $f->invoke('param');

    // 接口
    关键字:interface

    • 对象提供的与对象交互的方式就是接口。
    • 使用接口可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
    • 通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
    • 接口中定义的所有属性和方法都必须是public,可省略public关键字。
    • 接口中也可以定义常量(const)。接口常量和类常量的使用完全相同。
      可以用::访问。接口名::常量名,实现类::常量名。
      它们都是定值,可以被子类或子接口使用,但不能修改。
    • 接口不能定义属性!

    定义接口

    interface 接口名 {
    接口内容(公共方法声明的集合)
    }

    接口实现

    • 要实现一个接口,可以使用implements操作符。
    • 类中必须实现接口中定义的所有方法,否则会报一个fatal错误。
    • 如果要实现多个接口,可以用逗号来分隔多个接口的名称。
    • 实现多个接口时,接口中的方法不能有重名。
    • 接口也可以继承,通过使用extends操作符。
      class 类名 implements 接口名 {
      接口方法的实现
      }

    注意

    1. 类与抽象类之间是继承关系,类与接口之间是实现关系。
    2. 类与抽象类是单继承,类与接口是多实现。
    3. 接口不是类,限制类的结构。
    4. 接口与接口之间是多继承。用extends关键字。
        interface I_C extends I_A, I_B {}
    
    本文转载自http://blog.csdn.net/lhorse003/article/details/71170155
    

    相关文章

      网友评论

        本文标题:【转载】面向对象、类、接口- 不错的总结

        本文链接:https://www.haomeiwen.com/subject/umdrtftx.html