PHP抽象类与接口的区别实例详解

这篇文章主要介绍了PHP抽象类与接口的区别,结合实例形式分析了php抽象类与接口的概念、区别、使用方法及相关操作注意事项,需要的朋友可以参考下。

本文实例讲述了PHP抽象类与接口的区别,分享给大家供大家参考,具体如下:

抽象类abstract

概念

定义为抽象的类不能被实例化。任何一个类,如果有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的类。

继承一个抽象类的时候,子类必须定义父类中的所有抽象方法,这些方法的访问控制必须喝父类中一样或者更为宽松。

例如,某个抽象方法被声明为proteced,那么子类中的实现,就应该声明为protected或者public,而不能定义为private。

方法的调用方式必须匹配,即类型和所需参数数量必须一致,例如,子类定义了一个可选参数,而父类抽象方法中没有声明,则两者的声明并没有冲突。

特点

抽象类继承,使用关键字extends。

抽象类可以声明各种变量、常量、方法。

抽象类可以有构造函数。

抽象类中的方法可以是公开的public、保护的protected、私有的private。

一个类只能继承一个抽象类。

示例

示例一

  1. <?php
  2. // 抽象类
  3. abstract class AbstractClasss
  4. {
  5. // 强制要求子类定义这些方法
  6. abstract protected function getValue();
  7. abstract protected function prefixValue();
  8. // 普通方法(非抽象方法)
  9. public function printOut()
  10. {
  11. print $this->getValue() . "\n";
  12. }
  13. }
  14. // 子类
  15. class ConcreteClassOne extends AbstractClass
  16. {
  17. protected function getValue()
  18. {
  19. return "ConcreteClassOne";
  20. }
  21. public function prefixValues($prefix)
  22. {
  23. return "{$prefix}ConcreteClassOne";
  24. }
  25. }
  26. // 子类
  27. class ConcreteClassTwo extends AbstractClass
  28. {
  29. protected function getValue()
  30. {
  31. return "ConcreteClassTwo";
  32. }
  33. public function prefixValue($prefix)
  34. {
  35. return "{$prefix}ConcreteClassTwo";
  36. }
  37. }
  38. // 实例化第一个子类
  39. $classOne = new ConcreteClassOne;
  40. $classOne->printOut();
  41. echo $classOne->prefixValue('FOO_') . "\n";
  42. // 实例化第二个子类
  43. $classTwo = new ConcreteClassTwo;
  44. $classTwo->printOut();
  45. echo $classTwo->prefixValue('FOO_') . "\n";

结果输出

ConcreteClassOne

FOO_ConcreteClassOne

ConcreteClassTwo

FOO_ConcreteClassTwo

示例二

  1. <?php
  2. // 抽象类
  3. abstract class AbstractClass
  4. {
  5. // 我们的抽象方法仅需要定义需要的参数
  6. abstract protected function prefixName($name);
  7. }
  8. // 子类
  9. class ConcreteClass extends AbstractClass
  10. {
  11. // 我们的子类可以定义父类签名中不存在的可选参数
  12. public function prefixName($name, $separator = ".")
  13. {
  14. if ($name == "Pacman") {
  15. $prefix = "Mr";
  16. } elseif ($name == "Pacwoman") {
  17. $prefix = "Mrs";
  18. } else {
  19. $prefix = "";
  20. }
  21. return "{$prefix}{$separator} {$name}";
  22. }
  23. }
  24. // 实例化子类
  25. $class = new ConcreteClass;
  26. echo $class->prefixName("Pacman") . "\n";
  27. echo $class->prefixName("Pacwoman") . "\n";

结果输出

Mr. Pacman

Mrs, Pacwoman

接口interface

概念

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

要实现一个接口,使用implements操作符,类中必须实现接口中定义的所有方法。

特点

接口的实现,使用关键字implements。

接口中不能声明变量,但是可以声明常量。

接口中没有构造函数。

接口中的方法默认都是公开的public。

一个类可以实现多个接口。

示例

示例一 、 实现接口

  1. <?php
  2. // 声明一个iTemplate接口
  3. interface iTemplate
  4. {
  5. public function setVariable($name, $var);
  6. public function getHtml($template);
  7. }
  8. // 实现接口
  9. // 下面的写法是正确的
  10. class Template implements iTemplate
  11. {
  12. private $vars = array();
  13. public function setVariable($name, $var)
  14. {
  15. $this->vars[$name] = $var;
  16. }
  17. public function getHtml($template)
  18. {
  19. foreach($this->vars as $name => $value) {
  20. $template = str_replace('{' . $name . '}', $value, $template);
  21. }
  22. return $template;
  23. }
  24. }
  25. // 下面的写法是错误的,会报错,因为没有实现 getHtml()
  26. // Fatal error: Class BadTemplate contains 1 abstract methonds
  27. // and must therefore be declared abstaract (iTemplate::getHtml)
  28. class BadTemplate implements iTemplate
  29. {
  30. private $vars = array();
  31. public function setVariable($name, $var)
  32. {
  33. $this->vars[$name] = $var;
  34. }
  35. }

示例二 、 可扩充接口

  1. <?php
  2. interface a
  3. {
  4. public function foo();
  5. }
  6. interface b extends a
  7. {
  8. public function baz(Baz $baz);
  9. }
  10. // 正确的写法
  11. class c implements b
  12. {
  13. public function foo()
  14. {
  15. }
  16. public function baz(Baz $baz)
  17. {
  18. }
  19. }
  20. // 错误的写法会导致一个致命的错误
  21. class d implements b
  22. {
  23. public function foo()
  24. {
  25. }
  26. public function baz(Foo $foo)
  27. {
  28. }
  29. }

示例三 、 继承多个接口

  1. <?php
  2. interface a
  3. {
  4. pubLic function foo();
  5. }
  6. interface b
  7. {
  8. public function bar();
  9. }
  10. interface c extends a, b
  11. {
  12. public function baz();
  13. }
  14. class d implements c
  15. {
  16. public function foo()
  17. {
  18. }
  19. public function bar()
  20. {
  21. }
  22. public function baz()
  23. {
  24. }
  25. }

示例四 、使用接口常量

  1. <?php
  2. interface a
  3. {
  4. const b = 'Interface constant';
  5. }
  6. // 输出接口变量
  7. echo a:b;
  8. // 错误的写法,因为常量不能被覆盖。
  9. // 接口常量的概念和类常量的是一样的。
  10. class b implements a
  11. {
  12. const b = 'Class constant'
  13. }