文档章节

接口/抽象类/方法实现与重写/静态延迟绑定的一些知识点的梳理(PHP实例)

big_cat
 big_cat
发布于 2016/09/01 11:48
字数 1537
阅读 117
收藏 1

最容易混淆的知识点:

接口中的方法只能为 public

抽象方法可以为 public 和 protected,但不能为 private

如何理解:接口和抽象方法皆为方法的声明,需要让子类去实现方法体,这就要求子类必须有继承权限。同时,接口的扮演角色为对外部访问开放的一组标准,故需为 public。

实现必须以继承为前提,但重写和继承没有依赖关系。

实现的前提为继承,但重写并不需要有继承权限。你可以重写父类的 private 方法,虽然你并没有从父类继承此 private 方法,但依然受到父类的制约:参数必须完全一致。必须遵循重写时的权限可提升规则(子类重写的方法访问权限必须大于等于父类, public > protected > private)

1、Interface

接口是一个标准,是一个约定,而不是一种实现。

接口的目的是为了规范实现类。实现类需要实现接口中定义的所有方法,已实现接口标准化。

接口中的方法必须声明为 public。因为接口是一套对外开放的标准,之所以必须是 public 权限更倾向了表明对外访问控制层面,而不是子类的继承权限。

interface StudentInterface
{
    public function getName();
    public function setName($name);
    public function getClassInfo();
}

/**
 * Student 必须实现接口中声明的所有方法
 *
 */
class Student implements StudentInterface
{
    public $name;
    
    public function getName()
    {
        return $this->name;
    }
    
    public function setName($name)
    {
        $this->name = $name; 
    }

    public function getClassInfo()
    {
        
    }
}

2、抽象类与抽象方法

抽象类是由 abstract 关键字修饰的类,自身无法实例化,必须由子类继承(且当抽象类内部含有抽象方法时,子类需同时实现所有的抽象方法)。

抽象方法是由 abstract 关键之修饰的方法,只能存在于抽象类中(抽象类可以不含有抽象方法,但抽象方法必须声明在抽象类中)

<?php
//抽象类 可以不含抽象方法 但无法实例化
abstract class Foo
{
    public function getFoo()
    {
        echo __METHOD__ . PHP_EOL;
    }
}

//继承抽象类所有可继承的方法
class SubFoo extends Foo
{
}

//含有抽象方法的抽象类
abstract class Bar
{
    //抽象方法声明 不能被 private 修饰 因为需要被继承实现
    protected abstract function getBar();
}

//需要实现抽象父类的抽象方法
class SubBar extends Bar
{
    public function getBar()
    {
       echo __METHOD__ . PHP_EOL;
    }
}

这里要注意的还有 abstract 和 final 是对立的,abstract 要求此类必须被继承,final 则要求此类无法被继承

同时抽象方法不能修饰为 private 访问权限,因为抽象方法为声明,需被子类继承实现(注意这里我说的是实现,而不是重写,抽象方法没有函数体,没有重写一说)

3、继承与重写/继承与实现

不知道大家是不是有如下的认识,所谓重写是子类重新定义从父类继承的方法的函数体,错

重写和继承没有任何前后关系

你可以重写父类的 public/protected 方法,也可以重写父类的 private 方法(是的,你无权继承,但你依旧可以重写,但权利与义务对立统一,你可以重写的同时也收到了父类此 private 方法的制约)

实现则依赖于继承

你如果想实现父类的某方法声明时,父类可能是接口或者抽象类,则需要有继此方法的访问权限才可以。接口可能更偏向于其本质而规定所有方法声明使用 public,抽象方法则可以说完全是为了让子类继承实现,所以抽象方法必须为 public 或 protected

4、静态延迟绑定

PHP 5.3+ 的三大新特性:命名空间 自动载入 静态延迟绑定

php的继承模型中有一个存在已久的问题,那就是在父类中引用扩展类的最终状态比较困难

如何理解:“在父类中引用扩展类的最终状态比较困难” ,首先要明确的一点静态延迟绑定是针对类的属性或方法而言的,这一点并没有太多人提及,理解起来可能会认为“静态”是形容词,“延迟绑定”是主语,其实是静态属性或方法(类属性/方法)的延迟绑定。在 5.2 - 的版本中,难以在父类中定义一套静态属性和方法,使之能在被扩展类继承后,扩展类调用时可以切换为扩展类的上下文。而在 5.3+ 中, static 关键字的引入使此问题得以解决。

<?php

class Foo
{
    public static $property = "foo";

    // 5.2 -
    public static function getPropertyBySelf()
    {
        echo self::$property . PHP_EOL;
    }

    // 5.3 + 引入了静态绑定
    public static function getPropertyByStatic()
    {
        echo static::$property . PHP_EOL;
    }
}

class Bar extends Foo
{
    //注意此处重写父类属性后,内存中变分别为 Foo 和 bar 开辟了两个静态变量
    public static $property = "bar";

    public static function getPropertyByParent()
    {
        echo parent::$property . PHP_EOL;
    }

}

//self将属性固话在了父类中
Bar::getPropertyBySelf(); // foo
//虽然是在父类中定义的静态方法
//但通过延迟绑定 可以切换到子类的上下文
Bar::getPropertyByStatic(); // bar
//访问父类属性
Bar::getPropertyByParent(); //foo

静态工厂

<?php
/**
 * 通过 static 可以很方便的实现静态工厂类
 */
class Foo
{
    // self 无法延迟绑定 固化在了 Foo 中
    public static function getInstanceBySelf()
    {
        return new self();
    }

    // static 则静态延迟到调用上下文绑定
    public static function getInstanceByStatic()
    {
        return new static();
    }
}

class Bar extends Foo
{

}

var_dump(Bar::getInstanceBySelf()); //class Foo#1 (0) {}
var_dump(Bar::getInstanceByStatic()); //class Bar#1 (0) {}

可以看到 self 关键字是严格的绑定在定义类的上下文中的,而 static 在兼备 self 关键字特性的同时还具备了静态延迟绑定的特性,可以将类的属性和方法切换到调用类的上下文。

© 著作权归作者所有

big_cat
粉丝 49
博文 237
码字总数 162865
作品 0
长宁
后端工程师
私信 提问
C# 类与接口的几个问题的总结(待续)

1. 有关类的多态性 C#中,类的多态性是通过在子类中重载基类的虚方法(virtual标识)或函数成员来实现。 在C#中,继承、虚方法和重写方法组合在一起才能实现多态性。 2. 显式接口成员的使用 ...

橘子红了呐
2017/11/13
0
0
Java程序员从笨鸟到菜鸟之(三)面向对象之封装,继承,多态(下)

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188 上接:Java程序员从笨鸟到菜鸟之(二)面向对象之封装,继承,多态(上) 五:再谈继承 继承是一种联结类的层...

长平狐
2012/11/12
141
0
Java语言中的----抽象类、接口

day12 Java语言中的抽象类与接口 一、抽象类和接口概述; 在昨天我们学习了Java的继承功能,这个是一个核心知识点,今天我们再继承的基础之上学习一下抽象类和接口这两个知识。什么是抽象类?...

孤独一夜
2017/09/28
0
0
java继承/多态/接口基础知识

一、基础知识 1.this与super关键字的使用 a.this关键字 区分成员变量和局部变量 方法中出现局部变量和成员变量重名,可以在成员变量名前面加加以区分; this代表的是实例(对象),哪个实例(对...

lkee6760
2016/12/30
0
0
在Python中使用静态,类或抽象方法的权威指南

Python中方法的工作方式 方法是存储在类属性中的函数,你可以用下面这种方式声明和访问一个函数 Python在这里说明了什么?Pizza类的属性get_size是unbound(未绑定的),这代表什么含义?我们调...

程序猿拿Q
2018/10/30
313
1

没有更多内容

加载失败,请刷新页面

加载更多

nginx学习之模块

1、 stub_status模块: 用于展示nginx处理连接时的状态。 配置语法如下: Syntax:stub_status;Default:默认没有配置Context:server、location 可以编辑default.conf,加上如下配置: ...

码农实战
51分钟前
4
0
MySQL,必须掌握的6个知识点

目录 一、索引B+ Tree 原理 MySQL 索引 索引优化 索引的优点 索引的使用条件 二、查询性能优化使用 Explain 进行分析 优化数据访问 重构查询方式 三、存储引擎InnoDB MyISAM 比较 四、数据类...

李红欧巴
55分钟前
4
0
堆”和“栈

C++作为一款C语言的升级版本,具有非常强大的功能。它不但能够支持各种程序设计风格,而且还具有C语言的所有功能。我们在这里为大家介绍的是其中一个比较重要的内容,C++内存区域的基本介绍。...

SibylY
今天
4
0
总结:Https

一、介绍 简单理解,https即在http协议的基础上,增加了SSL协议,保障数据传输的安全性。 它由以前的http—–>tcp,改为http——>SSL—–>tcp;https采用了共享密钥加密+公开密钥加密的方式 ...

浮躁的码农
今天
6
0
数据库表与表之间的一对一、一对多、多对多关系

表1 foreign key 表2 多对一:表 1 的多条记录对应表 2 的一条记录 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 表2的多条记...

Garphy
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部