PHP面向对象-看父类调用子类方法
大部分面向对象编程语言中,父类是不允许调用子类的方法的,但是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面向对象-看父类调用子类方法的更多相关文章
- php 父类调用子类方法和成员
在C和C++里,父类都不允许调用子类的方法,但在php里可以.下面是一个调用的例子: <?php abstract class Animal { protected $name; public ...
- php面向对象编程 父类调用子类编程
使用父类调用子类的实现代码
- java 多态 ---父类调用子类方法
package test1;//多态的体现import javax.print.attribute.standard.RequestingUserName;import java.util.Scann ...
- Java父类与子类方法调用顺序
父类 FatherClass package 父类与子类方法调用顺序; /** * 父类 * @author shundong * */ public class FatherClass { priv ...
- Java 多态 父类和子类方法的访问控制权限
Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就 ...
- 多态&&父类调用子类特有的方法
/* 多态 1.没有继承就没有多态 2.代码的体现:父类类型的指针指向子类对象 3.好处:如果函数\方法参数使用的是父类对象,可以传入父类.子类对象 4.局限性: 1>父类类型的变量,不能直接调 ...
- java反射与多态(父类调用子类)的代码演示
package Test0817; import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method ...
- Python父类调用子类
首先说明,上面的标题其实是不正确的,Python是一门解释型.动态数据类型的高级语言,运行时,动态判断调用对象,其实还是子类自己在调用自己的方法或属性. 举个例子(copy过来的):SocketSer ...
- Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)
继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类 派生类Person ...
随机推荐
- Flash Builder4.7安装破解
引用自CSDN博客,日后我会上传FlashBuilder到百度网盘谢谢 http://bbs.csdn.net/topics/391036327
- RabbitMQ 发布订阅持久化
RabbitMQ是一种重要的消息队列中间件,在生产环境中,稳定是第一考虑.RabbitMQ厂家也深知开发者的声音,稳定.可靠是第一考虑,为了消息传输的可靠性传输,RabbitMQ提供了多种途径的消息持 ...
- java 5并发中的阻塞队列ArrayBlockingQueue的使用以及案例实现
演示一个阻塞队列的使用 public class BlockingQueueTest { public static void main(String[] args) { //创建一个包含三个元素的阻 ...
- java并发包——阻塞队列BlockingQueue及源码分析
一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...
- 20162330 第十二周 蓝墨云班课 hash
题目要求 利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75) 关键字集合:85,75,57,60,65,(你的8位学号 ...
- python API的安全认证
我们根据pid加客户端的时间戳进行加密md5(pid|时间戳)得到的单向加密串,与时间戳,或者其它字段的串的url给服务端. 服务端接收到请求的url进行分析 客户端时间与服务端的时间戳之差如果大于规 ...
- bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作
http://www.lydsy.com/JudgeOnline/problem.php?id=2333 读入所有数据,先模拟一遍所有的合并操作 我们不关心联通块长什么样,只关心联通块内有谁 所以可以 ...
- Python Tornado初学笔记之表单与模板(一)
Tornado中的表单和HTML5中的表单具有相同的用途,同样是用于内容的填写.只是不同的是Tornado中的表单需要传入到后台,然后通过后台进行对模板填充. 模板:是一个允许嵌入Python代码片段 ...
- 新概念英语(1-103)The French Test
Lesson 103 The French test 法语考试 Listen to the tape then answer this question. How long did the exam ...
- spring-oauth-server实践:授权方式四:client_credentials 模式的refresh_token?
spring-oauth-server入门(1-13)授权方式四:client_credentials 模式的refresh_token? 有效期内的反复申请access_token获取失效日期不变! ...