zoukankan      html  css  js  c++  java
  • PHP中抽象类与接口的区别

    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:
    类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。


    常量

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

      1 <?php
      2 
      3 // 声明一个'iTemplate'接口
      4 interface iTemplate
      5 {
      6     public function setVariable($name, $var);
      7     public function getHtml($template);
      8 }
      9 
     10 
     11 // 实现接口
     12 // 下面的写法是正确的
     13 class Template implements iTemplate
     14 {
     15     private $vars = array();
     16   
     17     public function setVariable($name, $var)
     18     {
     19         $this->vars[$name] = $var;
     20     }
     21   
     22     public function getHtml($template)
     23     {
     24         foreach($this->vars as $name => $value) {
     25             $template = str_replace('{' . $name . '}', $value, $template);
     26         }
     27  
     28         return $template;
     29     }
     30 }
     31 
     32 // 下面的写法是错误的,会报错,因为没有实现 getHtml():
     33 // Fatal error: Class BadTemplate contains 1 abstract methods
     34 // and must therefore be declared abstract (iTemplate::getHtml)
     35 class BadTemplate implements iTemplate
     36 {
     37     private $vars = array();
     38   
     39     public function setVariable($name, $var)
     40     {
     41         $this->vars[$name] = $var;
     42     }
     43 }
     44 ?>
     45 Example #2 可扩充的接口
     46 
     47 <?php
     48 interface a
     49 {
     50     public function foo();
     51 }
     52 
     53 interface b extends a
     54 {
     55     public function baz(Baz $baz);
     56 }
     57 
     58 // 正确写法
     59 class c implements b
     60 {
     61     public function foo()
     62     {
     63     }
     64 
     65     public function baz(Baz $baz)
     66     {
     67     }
     68 }
     69 
     70 // 错误写法会导致一个致命错误
     71 class d implements b
     72 {
     73     public function foo()
     74     {
     75     }
     76 
     77     public function baz(Foo $foo)
     78     {
     79     }
     80 }
     81 ?>
     82 Example #3 继承多个接口
     83 
     84 <?php
     85 interface a
     86 {
     87     public function foo();
     88 }
     89 
     90 interface b
     91 {
     92     public function bar();
     93 }
     94 
     95 interface c extends a, b
     96 {
     97     public function baz();
     98 }
     99 
    100 class d implements c
    101 {
    102     public function foo()
    103     {
    104     }
    105 
    106     public function bar()
    107     {
    108     }
    109 
    110     public function baz()
    111     {
    112     }
    113 }
    114 ?>
    115 Example #4 使用接口常量
    116 
    117 <?php
    118 interface a
    119 {
    120     const b = 'Interface constant';
    121 }
    122 
    123 // 输出接口常量
    124 echo a::b;
    125 
    126 // 错误写法,因为常量不能被覆盖。接口常量的概念和类常量是一样的。
    127 class b implements a
    128 {
    129     const b = 'Class constant';
    130 }
    131 ?>

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


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

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

     1 <?php
     2 abstract class AbstractClass
     3 {
     4  // 强制要求子类定义这些方法
     5     abstract protected function getValue();
     6     abstract protected function prefixValue($prefix);
     7 
     8     // 普通方法(非抽象方法)
     9     public function printOut() {
    10         print $this->getValue() . "
    ";
    11     }
    12 }
    13 
    14 class ConcreteClass1 extends AbstractClass
    15 {
    16     protected function getValue() {
    17         return "ConcreteClass1";
    18     }
    19 
    20     public function prefixValue($prefix) {
    21         return "{$prefix}ConcreteClass1";
    22     }
    23 }
    24 
    25 class ConcreteClass2 extends AbstractClass
    26 {
    27     public function getValue() {
    28         return "ConcreteClass2";
    29     }
    30 
    31     public function prefixValue($prefix) {
    32         return "{$prefix}ConcreteClass2";
    33     }
    34 }
    35 
    36 $class1 = new ConcreteClass1;
    37 $class1->printOut();
    38 echo $class1->prefixValue('FOO_') ."
    ";
    39 
    40 $class2 = new ConcreteClass2;
    41 $class2->printOut();
    42 echo $class2->prefixValue('FOO_') ."
    ";
    43 ?>
    44 以上例程会输出:
    45 
    46 ConcreteClass1
    47 FOO_ConcreteClass1
    48 ConcreteClass2
    49 FOO_ConcreteClass2
    50 Example #2 抽象类示例
    51 
    52 <?php
    53 abstract class AbstractClass
    54 {
    55     // 我们的抽象方法仅需要定义需要的参数
    56     abstract protected function prefixName($name);
    57 
    58 }
    59 
    60 class ConcreteClass extends AbstractClass
    61 {
    62 
    63     // 我们的子类可以定义父类签名中不存在的可选参数
    64     public function prefixName($name, $separator = ".") {
    65         if ($name == "Pacman") {
    66             $prefix = "Mr";
    67         } elseif ($name == "Pacwoman") {
    68             $prefix = "Mrs";
    69         } else {
    70             $prefix = "";
    71         }
    72         return "{$prefix}{$separator} {$name}";
    73     }
    74 }
    75 
    76 $class = new ConcreteClass;
    77 echo $class->prefixName("Pacman"), "
    ";
    78 echo $class->prefixName("Pacwoman"), "
    ";
    79 ?>
    80 以上例程会输出:
    81 
    82 Mr. Pacman
    83 Mrs. Pacwoman
    84 老代码中如果没有自定义类或函数被命名为“abstract”,则应该能不加修改地正常运行。

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


    延伸阅读:
    http://www.baidu.com/s?wd=php%20接口%20抽象类%20区别
    http://www.sogou.com/web?query=php%20接口%20抽象类%20区别
    https://www.so.com/s?q=php%20接口%20抽象类%20区别

    http://www.baidu.com/s?wd=php%20抽象类%20实例化

    抽象类:http://php.net/manual/zh/language.oop5.abstract.php
    接口:http://php.net/manual/zh/language.oop5.interfaces.php

    PHP高级——抽象类与接口的区别: http://www.cnblogs.com/picaso/archive/2012/10/05/2711865.html
    php抽象类和接口: http://www.cnblogs.com/hylaz/archive/2012/11/11/2765397.html

  • 相关阅读:
    11.2---字符串数组排序,删除变位词(CC150)
    9.10---堆箱子问题(CC150)
    9.9---n皇后问题(CC150)
    11.1---有序数组合并(CC150)
    9.8---硬币问题(CC150)
    7.7---找只含3,5,7的数(CC150)
    17.1---编写一个函数交换两个变量的值(CC150)
    7.6--找过点最多的直线(CC150)
    7.5---两个正方形分成对半的直线(CC150)
    9.5---括号是否有效(CC150)
  • 原文地址:https://www.cnblogs.com/caihuafeng/p/5484220.html
Copyright © 2011-2022 走看看