面向对象的PHP,带有关键字Interface,extends,implements

时间:2011-03-18 05:43:09

标签: php oop

在过去的几个月里,我在学习纯粹的oop方面取得了长足的进步,现在我正在将设计模式应用到我的工作中!所以我不得不扩展我的PHP知识,我正在使用接口,扩展它们,然后为这些接口实现类。我的问题是关于从一个扩展另一个接口的接口构造一个类,例如:

interface Car
{
  function doGeneralCarStuff();
  vinNumber =;
}

interface CompactCar extends Car
{
   static $numCompactCars;
   function doCompactCarStuff();
}

class HondaCivic implements CompactCar
{
   function doGeneralCarStuff()
   {
     //honk horn , blink blinkers, wipers on, yadda yadda
   }

   function doCompactCarStuff()
   {
      //foo and bar and foobar
   }

}

class ToyotaCorolla implements CompactCar
{
   function doGeneralCarStuff()
   {
     //honk horn , blink blinkers, wipers on, yadda yadda
   }

   function doCompactCarStuff()
   {
      //foo and bar and foobar
   }

}


myCar = new HondaCivic();
myFriendCar = new ToyotaCorolla();

好的,现在让我说我想了解一下我的本田扩展的接口之一,即CompactCar接口。我想知道有多少紧凑型轿车($ numCompactCars)已经创建。我是新手(对我来说很深:p)OOP,所以如果我没有正确地做这件事,请提供指导。非常感谢!

3 个答案:

答案 0 :(得分:3)

Factory模式的唯一缺点是你可以随时绕过它 - 即new HondaCivic()会扰乱车数。

这是更强大的东西:

<?php

interface Car
{
  function doGeneralCarStuff();
}

// Declare as abstract so it can't be instantiated directly
abstract class CompactCar
{
   // Increment car count
   function __construct() {
        CompactCar::$numCompactCars++;   
   }
   function __clone() {
       CompactCar::$numCompactCars++; 
   }
   // Decrement car count
   function __destruct() {
        CompactCar::$numCompactCars--;   
   }
   // Prevent external modification of car count
   protected static $numCompactCars;
   // Get the current car count
   static public function getCount() {
        return CompactCar::$numCompactCars;   
   }
   // Require a compact car function for descendant classes
   abstract public function doCompactCarStuff();
}

// Extend and implement
class HondaCivic extends CompactCar implements Car
{
   function doGeneralCarStuff() { }
   function doCompactCarStuff() { }
}

// Extend and implement
class ToyotaCorolla extends CompactCar implements Car
{
   function doGeneralCarStuff() { }
   function doCompactCarStuff() { }
}

$myCar = new HondaCivic();  // 1 car 
$myFriendCar = new ToyotaCorolla();  // 2 cars
printf("Number of compact cars: %d\n", CompactCar::getCount());
$myCar = new HondaCivic();  // still only 2 cars
unset($myFriendCar);  // one car left!
printf("Number of compact cars: %d\n", CompactCar::getCount());
$myCar2 = clone $myCar; // now we have two cars again
printf("Number of compact cars: %d\n", CompactCar::getCount());
CompactCar::$numCompactCars = 1000;  // sorry, you can't do that!

答案 1 :(得分:2)

如果将“新车”存储在一个数组中,您可以轻松地遍历它们并检查是否实现了给定的接口。类似的东西:

$cars['myCar'] = new HondaCivic();
$cars['myFriendCar'] = new ToyotaCorolla();

$compact_counter = 0;
foreach ($cars as $car)
  if ($car instanceof CompactCar)
    $compact_counter ++;

$compact_counter将有多少小型车已经实施。

答案 2 :(得分:2)

在我看来,你正试图在界面上存储数据。这不是接口可以做的事情。接口用于描述类从外部看起来的样子,而不是用于实际实现功能。

您想要的可能是常规的类层次结构,例如:

class Car {

    public function doGeneralCarStuff()
    {
      //honk horn , blink blinkers, wipers on, yadda yadda
    }

}

class CompactCar extends Car {

    public static $numCompactCars = 0;

    public function __construct()
    {
        self::$numCompactCars++;
    }

    public function doCompactCarStuff()
    {
        //foo and bar and foobar
    }
}

class HondaCivic extends CompactCar {

    public function __construct()
    {
        parent::__construct();
        // do Honda Civic stuff
    }

}

class ToyotaCorolla extends CompactCar
{
    public function __construct()
    {
        parent::__construct();
        // do Corolla stuff
    }
}

$myCar = new HondaCivic();
$myFriendCar = new ToyotaCorolla();
echo CompactCar::$numCompactCars; // -> 2

接口更适合描述不一定继承的特征,例如:

interface HasSunroof {
    function openSunroof();
    function closeSunroof();
}

在某些语言(Javascript,Ruby等)中HasSunroof可能是“mixin”并且具有与之关联的数据和功能,但在PHP(和Java等)中,您必须将功能放在实现接口的类。

接口(根据我的经验)更常用于编译时类型检查的语言,如Java,而不是像PHP这样的“鸭子类型”语言。

相关问题