PHP Duck Sample - Head First - Design Patterns - Chapter One
This is the first question I ask from many others to come.
Someone here might call me crazy because I'm following the mentioned book in the question's Title using PHP-OO.
At the first chapter, the authors introduce a simple project called 'SimUDuck' and, although I've reproduced the same in Java, I was wondering to reproduce the same using PHP.
At the end, the SimUDuck's project creates two (2) interfaces (FlyBehavior and QuackBehavior), more than five (5) classes implementing those interfaces (e.g. FlyWithWings(), Quack() etc), an abstract class called Duck and three (3) or four (4) different ducks species classes extending Duck (Mallard, HeadRedDuck, RubberDuck etc), just to demonstrate how important is to program for interface.
To simulate the Java main method environment, I've created a PHP class called MiniDuckSimulator, including the function 'public static function main()' and in the same script I've added "MiniDuckSimulator::main();". The script works without errors.
The intriguing issue is that without call any QuackBehavior::quack() implemented method, the echo 'Quack!quack!' appears. Those who has read this book knows what I'm talking about.
Note: Below is a particular part of the script:
interface FlyBehavior {
public function fly();
}
interface QuackBehavior {
public function quack();
}
include_once 'FlyBehavior.php';
class FlyWithWings implements FlyBehavior {
public function fly() {
echo 'I'm flying!<br />';
}
}
include_once 'QuackBehavior.php';
class Quack implements QuackBehavior {
public function quack() {
echo 'Quack!<br />';
}
}
abstract class Duck {
protected $flyBehavior;
protected $quackBehavior;
function __construct() {
}
public f开发者_StackOverflow社区unction performFly(){
$this->flyBehavior->fly();
}
public function performQuack(){
$this->quackBehavior->quack();
}
public function setFlyBehavior($flyBehavior){
$this->flyBehavior = $flyBehavior;
}
public function swim(){
echo "All the ducks float, including the decoy!<br />";
}
}
include_once 'Duck.php';
include_once 'FlyWithWings.php';
include_once 'Quack.php';
class Mallard extends Duck {
function __construct() {
$this->flyBehavior = new FlyWithWings();
$this->quackBehavior = new Quack();
}
}
class MiniDuckSimulator {
public static function main(){
$mallard = new Mallard();
$mallard->performFly();
}
}
MiniDuckSimulator::main();
Thanks in advance.
LucDaher.
The reason you are seeing Quack!<br />
output is because of this:
class Quack implements QuackBehavior {
public function quack() {
echo 'Quack!<br />';
}
}
Here's your problem: If you simply run new Quack();
the quack()
method is automatically being executed by php as a constructor because it is the same name as your class. -- I see you referenced Java in your question, so this shouldn't be a foreign concept to you.
new Quack(); // => Quack!<br />
A potentially better way
<?php
interface CanFly {
public function fly();
}
interface CanQuack {
public function quack();
}
abstract class Duck implements CanFly, CanQuack {
protected $color = "DEFAULT"
public function fly(){
echo "I'm flying with my {$this->color} wings\n";
}
public function quack(){
echo "I'm quacking\n";
}
public function swim(){
echo "I'm swimming\n";
}
}
class Mallard extends Duck {
public function __construct(){
$this->color = "green";
}
public function quack(){
echo "My quack sounds more like a honk\n";
}
}
$m = new Mallard();
$m->fly();
$m->quack();
$m->swim();
?>
Output
I'm flying with my green wings
My quack sounds more like a honk
I'm swimming
In your situation, I would personally assume that I've overlooked something when saying that an echo is being reached in the code without a call to that method. I can't see a way that this would be possible.
Reanalyze your code and look for a sneaky way that your echo 'Quack!quack!' is being reached.
Comment this line:
echo 'Quack!<br />';
Do you see any more quacks? If so, then there is an echo/exit/die in your code with this string!
It is because when you have the class with the same name of the method, the PHP consider it as a constructor. This is already deprecated in php 7 and it will be discontinued soon. You can see it on the online documentation: http://php.net/manual/en/migration70.deprecated.php
精彩评论