欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

php中接口和抽象类的区别是什么

程序员文章站 2022-03-17 23:26:42
...

区别为:1、接口是通过interface关键字来定义的,抽象类是通过abstract关键字来定义的;2、接口没有数据成员,但是抽象类有数据成员,抽象类可以实现数据的封装;3、接口没有构造函数,抽象类可以有构造函数。

php中接口和抽象类的区别是什么

本教程操作环境:windows7系统、PHP7.1版,DELL G3电脑

1、抽象类与接口的区别

在学习PHP面向对象时,都会在抽象类与接口上迷惑,作用差不多为什么还那么容易混淆,何不留一去一?但是事实上两者的区别还是很大的,如果能够很好地运用PHP的两个方法,面向对象的程序设计将会更加合理、清晰高效。

a.接口是通过 interface 关键字来定义的, 抽象类是通过abstract关键字来定义的。
b.对接口的使用方式是通过关键字implements来实现的,而对于抽象类的操作是使用类继承的关键字extends实现的,使用时要特别注意。
c.接口没有数据成员,但是抽象类有数据成员,抽象类可以实现数据的封装。
d.接口没有构造函数,抽象类可以有构造函数。
e.接口中的方法都是public类型,而抽象类中的方法可以使用private、protected或public来修饰。
f.一个类可以同时实现多个接口,但是只能实现一个抽象类。

相同点:抽象方法与接口的函数体内不能写任何东西,连两个大括号都不能写!!!如:function getName();这样就行了

2、接口

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口中定义的所有方法都必须是公有,这是接口的特性。

实现(implements)

要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。

Note:
实现多个接口时,接口中的方法不能有重名。

Note:
接口也可以继承,通过使用 extends 操作符。

Note:
类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。

常量

接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。

 <?php

// 声明一个'iTemplate'接口
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}


// 实现接口
// 下面的写法是正确的
class Template implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }

    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }

        return $template;
    }
}

// 下面的写法是错误的,会报错,因为没有实现 getHtml():
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
}
?>
Example #2 可扩充的接口

<?php
interface a
{
    public function foo();
}

interface b extends a
{
    public function baz(Baz $baz);
}

// 正确写法
class c implements b
{
    public function foo()
    {
    }

    public function baz(Baz $baz)
    {
    }
}

// 错误写法会导致一个致命错误
class d implements b
{
    public function foo()
    {
    }

    public function baz(Foo $foo)
    {
    }
}
?>
Example #3 继承多个接口

<?php
interface a
{
    public function foo();
}

interface b
{
    public function bar();
}

interface c extends a, b
{
    public function baz();
}

class d implements c
{
    public function foo()
    {
    }

    public function bar()
    {
    }

    public function baz()
    {
    }
}
?>
Example #4 使用接口常量

<?php
interface a
{
    const b = 'Interface constant';
}

// 输出接口常量
echo a::b;

// 错误写法,因为常量不能被覆盖。接口常量的概念和类常量是一样的。
class b implements a
{
    const b = 'Class constant';
}
?>

http://php.net/manual/zh/language.oop5.interfaces.php

3、抽象类

PHP 5 支持抽象类和抽象方法。定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 这也适用于 PHP 5.4 起的构造函数。在 PHP 5.4 之前的构造函数声明可以不一样的。

<?php
abstract class AbstractClass
{
 // 强制要求子类定义这些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>
以上例程会输出:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
Example #2 抽象类示例

<?php
abstract class AbstractClass
{
    // 我们的抽象方法仅需要定义需要的参数
    abstract protected function prefixName($name);

}

class ConcreteClass extends AbstractClass
{

    // 我们的子类可以定义父类签名中不存在的可选参数
    public function prefixName($name, $separator = ".") {
        if ($name == "Pacman") {
            $prefix = "Mr";
        } elseif ($name == "Pacwoman") {
            $prefix = "Mrs";
        } else {
            $prefix = "";
        }
        return "{$prefix}{$separator} {$name}";
    }
}

$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
以上例程会输出:

Mr. Pacman
Mrs. Pacwoman
老代码中如果没有自定义类或函数被命名为“abstract”,则应该能不加修改地正常运行。

http://php.net/manual/zh/language.oop5.abstract.php

推荐学习:《PHP视频教程

以上就是php中接口和抽象类的区别是什么的详细内容,更多请关注其它相关文章!