I have come a long way in the past few months in learning pure oop, and now I am applying design patterns to my work! So I have had to expand my php knowledge, and I am using interfaces, extending them, and then implementing the classes for those interfaces. My question is about constructing a class from an interface which extends another take this code for instance:
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 doCompactCarStu开发者_如何学编程ff()
{
//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();
OK, now lets say I want to know something about one of the interfaces from which my Honda extends i.e. the CompactCar interface. I want to know how many compact cars ($numCompactCars) have been created. I am new to deep ( deep for me :p ) OOP, so please provide guidance if I am not doing this correctly. Thanks so much!
The only downside with the Factory pattern is that you can bypass it at any time - i.e, new HondaCivic()
will upset the car count.
Here's something more robust:
<?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!
if you store your 'new cars' in an array you can easily loop through them and check if the implement a given interface. Something like:
$cars['myCar'] = new HondaCivic();
$cars['myFriendCar'] = new ToyotaCorolla();
$compact_counter = 0;
foreach ($cars as $car)
if ($car instanceof CompactCar)
$compact_counter ++;
$compact_counter
will have how many compact cars have been implemented.
It looks to me like you're trying to store data on the interface. This isn't something interfaces can do. Interfaces are for describing what a class should look like from the outside, not for actually implementing functionality.
What you want is probably a regular class hierarchy, like:
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
An interface would be more appropriate for describing a feature that isn't necessarily inherited, eg:
interface HasSunroof {
function openSunroof();
function closeSunroof();
}
In some languages (Javascript, Ruby, etc) HasSunroof
could be a "mixin" and have data and functionality associated with it, but in PHP (and Java, etc) you have to put the functionality in the class that implements the interface.
Interfaces (in my experience) are more frequently used in languages with compile-time type checking, like Java, than they are in "duck typed" languages like PHP.
精彩评论