在写一个通用的通知类时,遇到了问题,特此查看一下抽象类跟接口的异同点。

示例

interface a
{
    function run();
}
interface b
{
    const HELLO = "b: Hello, World!\n";
    static function hello();
}
interface c extends a,b
{
    public function info($str);
}
abstract class d implements c
{
    public $hello = "d: hello, world!\n";

    public function run(){
        echo "d: run()\n";
        self::hello();
    }
    static function hello(){
        echo "d: hello()\n";
        echo self::HELLO;
    }
    abstract function info($str);
}
abstract class e extends d
{
    protected $info = "e: info\n";
    private $msg;

    private function setMsg($msg){
        echo "e: setMsg()\n";
        $this->msg = $msg;
    }
    protected function getMsg(){
        echo "e: getMsg()\n";
        if(is_null($this->msg)) $this->setMsg("e: msg\n");
        return $this->msg;
    }
    public function dumpMsg(){
        echo "e: dumpMsg()\n";
        return $this->getMsg();
    }

    public function info($str){
        echo "e: info\n";
        echo $this->getMsg(), $this->msg($str);
    }

    abstract function msg($str);
}
class m extends e
{
    public $msg = "m: msg\n";

    public function msg($str){
        echo "m: msg()\n";
        echo $this->msg;
        return str_replace("\n", ', ', $this->info . $this->getMsg() . $str) . "\n";
    }
}
class n extends m
{
    public function run(){
        echo "n: run()\n";
        parent::run();
        echo $this->hello;
    }

    public function show(){
        echo "n: show()\n";
        $this->info('foo');
        $this->msg('bar');
        echo $this->msg;
        echo $this->dumpMsg();
    }
}

$obj = new n();
$obj->run();
echo "\n";
$obj->show();

异同

只要有一个方法为抽象方法,则这个类就是抽象类,抽象类是介于接口和类之间的特殊存在,是个“半成品”,不能实例化。

  1. 接口中的方法和抽象类中的抽象方法都要重写
  2. 重写的方法可访问权限不能变

  • 接口
    1. 没有函数体
    2. 没有成员变量
    3. 所有方法都必须可访问
    4. 可继承多个接口
  • 抽象类
    1. 抽象方法没有函数体
    2. 有成员变量
    3. 可以有受保护或者私有的属性和方法
    4. 可实现多个接口或者继承一个类

参考文章