大部分面向对象编程语言中,父类是不允许调用子类的方法的,但是PHP中可以

1、父类调用子类方法示例

class A

{

public function testa()

{

$this->testb();

}

}

class B extends A

{

//仅对public方法可以进行父类调用子类

public function testb()

{

echo 'bbbbb';

}

}

$b = new B();

$b->a();

//输出bbbbb

2、弊端

尽量避免这么写,这样的设计非常不好,如果需要写这样的代码,那么一定有其他的设计模式可以取代它

3、好的设计方法

首先发现父类调用子类这种方式是在Yii2.0中的save方法,这个方法位于\yii\db\BaseActiveRecord中,save方法中调用了insert或者update方法,然而在当前类中并没有找到这两个方法,因为BaseActiveRecord实现了ActiveRecordInterface接口,所以应该是必须要实现这两个方法的,但这两个方法却出现在了他的子类\yii\db\ActiveRecord中,也就是子类实现了

两个知识点:

  • 父类可以调用子类的方法
  • 如果一个抽象类实现了一个接口,那么它可以不实现接口中方法、而由子类去实现

这样的好处是:如果接口中新增了方法、并且所有的子类都是需要做相同的实现,那么就可以直接将实现放在这个抽象类中,否则对应的各个子类去各自实现

//yii2.0

interface ActiveRecordInterface

{

public function update($runValidation = true, $attributeNames = null);

public function insert($runValidation = true, $attributes = null);

}

//BaseActiveRecord实现了ActiveRecordInterface接口

abstract class BaseActiveRecord extends Model implements ActiveRecordInterface

{

public function save($runValidation = true, $attributeNames = null)

{

if ($this->getIsNewRecord()) {

return $this->insert($runValidation, $attributeNames);

} else {

return $this->update($runValidation, $attributeNames) !== false;

}

}

}

//ActiveRecord

class ActiveRecord extends BaseActiveRecord

{

public function insert($runValidation = true, $attributes = null)

{

//具体实现

}

public function update($runValidation = true, $attributeNames = null)

{

//具体实现

}

}

4、应用

如最近的需求:新建了语文、数学、英语三科错题数据库表,目前结构表结构基本一致,但未来可能不同的错题可能会有不同的差异,所以分开三个库建了三张表

对于目前来说三科都需要查询错题数量统计,这个时候一种做法是三个类分别去实现这个方法,另外一种方式就是可以定义一个接口,接口中定义统计的方法、目前来说并无差异,所以为三个错题的类建立一个抽象的基类,并将统计错题的方法在抽象基类中实现,如果以后出现了不同的统计方式,子类可以直接重写这个统计方法

如果表发生了改变,统计方法发生了改变,查询依赖于对应科目表中的不同字段,也就是具体数学|语文|英语错题中的变量、常量、或方法,就可以直接在接口中定义、在子类中实现、在抽象基类中调用子类的这个方法

//实例 定义一个接口 里面包含计算错题统计的方法

interface WrongNoteInterface

{

public function statistics();

//public function select();

//public function where();

}

//抽象基类

abstract class WrongNoteBase implements WrongNoteInterface

{

public function statistics()

{

$select = 'xx’;// $select = $this->select();

$where = ‘xx’;// $where = $this->where();

return $this->find()->select($select)->where($where)->asArray()->all();

}

}

//语数外继承基类

class ChineseWrongNote extends WrongNoteBase

{

const IS_RIGHT_0 = 0;

const IS_RIGHT_1 = 1;

}

像上面的这种情况,如果要查的字段select变了,select可能是个SUM(xxx)这中结构,而其中计算SUM的条件可能不一样,这个时候就可以在接口中添加:

  • public function select();
  • public function where();

    然后在修改statistics中$select获取方式变为直接调用子类方法select,代码改为注释中的内容

总结:经过这样的修改,避免了代码的冗余(一个统计代码复制三份)、可以方便的对类进行扩展

PHP面向对象-看父类调用子类方法的更多相关文章

  1. php 父类调用子类方法和成员

    在C和C++里,父类都不允许调用子类的方法,但在php里可以.下面是一个调用的例子: <?php abstract class Animal { protected $name; public ...

  2. php面向对象编程 父类调用子类编程

    使用父类调用子类的实现代码

  3. java 多态 ---父类调用子类方法

    package test1;//多态的体现import javax.print.attribute.standard.RequestingUserName;import java.util.Scann ...

  4. Java父类与子类方法调用顺序

    父类 FatherClass package 父类与子类方法调用顺序; /** * 父类 * @author shundong * */ public class FatherClass { priv ...

  5. Java 多态 父类和子类方法的访问控制权限

    Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就 ...

  6. 多态&&父类调用子类特有的方法

    /* 多态 1.没有继承就没有多态 2.代码的体现:父类类型的指针指向子类对象 3.好处:如果函数\方法参数使用的是父类对象,可以传入父类.子类对象 4.局限性: 1>父类类型的变量,不能直接调 ...

  7. java反射与多态(父类调用子类)的代码演示

    package Test0817; import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method ...

  8. Python父类调用子类

    首先说明,上面的标题其实是不正确的,Python是一门解释型.动态数据类型的高级语言,运行时,动态判断调用对象,其实还是子类自己在调用自己的方法或属性. 举个例子(copy过来的):SocketSer ...

  9. Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)

    继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类  派生类Person         ...

随机推荐

  1. windows上SSH服务连接远程主机失败

    putty连接出现错误提示"Network error:connection refused",xshell连接出现错误提示"connection failed:(por ...

  2. 第一次使用github、git工具,本地仓库、远程仓库使用

    一次使用git,记录下使用过程...可能还有很多东西可能还没理解,后期理解了再写吧 git是什么.,百度的回答: 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 使用过程一直在百度 ...

  3. Konckout第六个实例:自定义组件 -- 发表评论

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. java排序算法(十):桶式排序

    java排序算法(十):桶式排序 桶式排序不再是一种基于比较的排序方法,它是一种比较巧妙的排序方式,但这种排序方式需要待排序的序列满足以下两个特征: 待排序列所有的值处于一个可枚举的范围之类: 待排序 ...

  5. Sublime Text、webstorm等编译器快速编写HTML/CSS代码的技巧

    Sublime Text.webstorm等编译器,如果你从事Web前端开发的话,对这几款软件一定不会陌生.它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演 ...

  6. Java注解(1)-注解基础

    注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解 ...

  7. 自定义ArrayList

    自定义实现ArrayList很简单,只需要明白下面几点 1.ArrayList 底层是由数组组成的 2.数组有容量限制,但是ArrayList并没有(实际上也有,Integer.MAX_VALUE). ...

  8. JavaScript(第二十二天)【动态加载js和css】

    学习要点: 1.元素位置 2.动态脚本 3.动态样式 本章主要讲解上一章剩余的获取位置的DOM方法.动态加载脚本和样式.   一.元素位置 上一章已经通过几组属性可以获取元素所需的位置,那么这节课补充 ...

  9. JavaScript(第二天)【语法,变量】

    一.语法构成 区分大小写 ECMAScript中的一切,包括变量.函数名和操作符都是区分大小写的.例如:text和Text表示两种不同的变量.   标识符 所谓标识符,就是指变量.函数.属性的名字,或 ...

  10. Alpha第九天

    Alpha第九天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...