php中abstract和interface的区别

转载链接
1.https://www.cnblogs.com/songanwei/p/9389005.html#!comments
2.https://blog.csdn.net/qq_22630169/article/details/103490595
3.https://www.cnblogs.com/jimz/p/9375261.html
4.https://www.php.net/manual/zh/language.oop5.interfaces.php

1.abstract

<?php

// 1.声明抽象方法的必须声明为抽象类
//2.抽象类不能被实例化  new AbstractClass();会报错
//3.抽象方法不能定义具体功能实现,只是声明其调用方式,不能呢过定义其具体功能实现
abstract class AbstractClass{
    abstract protected function getValue();
    abstract protected function getPrefixValue($prefix);
    public function printOut()
    {
        print $this->getValue();
    }
}

//继承一个抽象类的时候,子类必须实现父类的抽象方法
//这些访问控制必须和父类一样或者更为宽松
//父类中的抽象方法必须和子类中实现方法的参数类型和数量一致(有待确认,可以加默认参数)
//例如,子类的实现的抽象方法中定义一个可选参数,而父类中声明没有,则两者并无冲突;父类抽象方法有,子类没有也可以
class ConcreteClass1 extends AbstractClass{
    protected function getValue($value="")
    {
        return "ConcreteClass1";
    }

    public function getPrefixValue($prefix)
    {
        // TODO: Implement getPrefixValue() method.
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass{
    protected function getValue()
    {
        // TODO: Implement getValue() method.
        return "ConcreteClass2";
    }

    public function getPrefixValue($prefix,$separator="")
    {
        // TODO: Implement getPrefixValue() method.
        return "{$prefix}ConcreteClass2".$separator;
    }
}


$class1 = new ConcreteClass1();
$class1->printOut();
echo $class1->getPrefixValue("FOO_");

$class2 = new ConcreteClass2();
$class2->printOut();
echo $class2->getPrefixValue("FOO_","ON");

2.interface

<?php
//接口通过interface关键字定义的,定义的方法都是空的
//接口中的方法必须是public公有的,这是接口的特性
//接口使用extends可以被继承
//接口中可以定义常量,和类常量的使用完全相同,但是不能被子类或者子接口覆盖ia
interface ITemplate
{
    const a = "ITemplate Interface constant";

    public function setVariable($name,$var);
    public function getHtml($template);
    public function __construct();
}
//echo ITemplate::b;
interface NTemplate{
    const b = "NTemplate Interface constant";
    public function next();
    public function getHtml($template);
}

interface IITemplate extends ITemplate{

    public function II(Baz $baz);
}

//实现一个接口,使用implements操作符号
//类继承接口 必须全部实现接口中的方法
//类可以实现多个接口,使用逗号分隔多个接口的名称
//类要实现接口,必须和接口中定义的方法完全一致
class Template implements iTemplate ,NTemplate,IITemplate
{
    private $vars = array();
    public function __construct()
    {

    }

    public function setVariable($name, $var)
    {
        // TODO: Implement setVariable() method.
        $this->vars[$name] = $var;
    }

    public function getHtml($template)
    {
        // TODO: Implement getHtml() method.
        var_dump($template);
    }

    public function Next()
    {

    }
    public function II(Baz $baz)
    {
        // TODO: Implement II() method.
    }
}

echo Template::a;

3.区别

相同:
1.都不能实例化
2.子类必须实现定义的抽象方法
不同:
1.抽象类由abstract定义,接口由interface定义
2.抽象类的方法可以是public,protected,private,而intreface的访问控制只能是public
3.抽象类中可以定义普通成员变量,接口不能
4.抽象类中可以写具体实现方法(包括构造函数),而接口只能声明函数名称,没有函数实体,必须是抽象的
5.抽象类使用extends单继承;接口使用implements 实现,可以多继承,使用“,”分隔;并且接口之间可以使用extends继承
6.抽象类中定义的方法和子类可以扩展,而interface中声明的方法必须一致

4.应用场景

1.abstract使用场景
通常,在子类和父类之间存在逻辑上的层次结构是应当使用抽象类,而在希望支持差别较大的两个或多个对象之间的特定交互行为时,就应当使用接口。

创业做网站  
到底用什么数据库?  mysql, oracle,sqlserver,postgresql?  
这样:先开发网站,运行再说.  
先弄个mysql开发着,正式上线了再数据库也不迟  
引来问题:  
换数据库,会不会以前的代码又得重写?:不必,用抽象类  
开发者,开发时,就以db抽象类来开发.  
*/   
abstract class db {   
    public abstract function connect($h,$u,$p);   
    public abstract function query($sql);   
    public abstract function close();   
}  
下面这个mysql类,严格实现了db抽象类  
试想: 不管上线时,真正用什么数据库  
我只需要再写一份如下类  
class oracle extends db {  
}  
class mssql extends db {  
}  
class postsql extends db {  
}  
业务逻辑层不用改?  
为什么不用改?  
因为都实现的db抽象类.  
我开发时,调用方法不清楚的地方,我就可以参考db抽象类.  
反正子类都是严格实现的抽象类.  
*/   
class mysql extends db {   
    public function connect($h,$h,$u) {   
        return true;   
    }   
    public function query($sql) {   
    }   
    public function close() {   
    }   
}   

Thinkphp框架中就使用abstract定义的

在这里插入图片描述

2.intreface使用场景
当多个对象不能抽象出共同的父类,但是有共同的行为,这种情况下就需要将这种行为封装成接口。比如登记这种行为:人,汽车,房子都需要登记,但是这三类没有共同的特征,所以要将登记这一行为封装成一个接口。再如:电脑的USB接口使用,如果符合USB接口规范,就可以插进去,并且读取或写入数据,但是 手机,U盘,MP3他们不是同一种类型,所以要将USB接口单独封装出来。

/*  
接口 就更加抽象了  
比如一个社交网站,  
关于用户的处理是核心应用.  
登陆  
退出  
写信  
看信  
招呼  
更换心情  
吃饭  
骂人  
捣乱  
示爱  
撩骚  
这么多的方法,都是用户的方法,  
自然可以写一个user类,全包装起来  
但是,分析用户一次性使不了这么方法  
用户信息类:{登陆,写信,看信,招呼,更换心情,退出}  
用户娱乐类:{登陆,骂人,捣乱,示爱,撩骚,退出}  
开发网站前,分析出来这么多方法,  
但是,不能都装在一个类里,  
分成了2个类,甚至更多.  
作用应用逻辑的开发,这么多的类,这么多的方法,都晕了.  
*/   
interface UserBase {   
    public function login($u,$p);   
    public function logout();   
}   
interface UserMsg {   
    public function wirteMsg($to,$title,$content);   
    public function readMsg($from,$title);   
}   
interface UserFun {   
    public function spit($to);   
    public function showLove($to);   
}   
/*  
作为调用者, 我不需要了解你的用户信息类,用户娱乐类,  
我就可以知道如何调用这两个类  
因为: 这两个类 都要实现 上述接口.  
通过这个接口,就可以规范开发.  
*/   
/*  
下面这个类,和接口声明的参数不一样,就报错,  
这样,接口强制统一了类的功能  
不管你有几个类,一个类中有几个方法  
我只知道,方法都是实现的接口的方法.  
*/   
class User implements UserBase {   
    public function login($u) {   
    }   
}   
?>  

备注:这道题的思路是先从总体解释抽象类和接口的基本概念,然后再比较两者的语法细节,最后再说两者的应用区别。
比较两者语法细节区别的条理是:先从一个类中的构造方法、普通成员变量和方法(包括抽象方法),静态变量和方法,继承性等6个方面逐一去比较回答,接着从第三者继承的角度的回答,特别是最后用了一个典型的例子来展现自己深厚的技术功底。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值