I am a very beginning in PHP and Design Patterns. I have been studying the amazing Head First Design patterns. So, I have been trying to translate the original to PHP. However, I must be doing things very wrong, because it is not working. Can you help me?
<?php
interface FlyBehavior{
public function fly();
}
class FlyWithWings implements FlyBehavior{
public function fly(){
echo "I am flying!";
}
}
class FlyNoWay implements FlyBehavior{
public function fly(){
echo "I cannot fly!";
}
}
interface QuackBehavior{
public function quack();
}
class Quack implements QuackBehavior{
public function quack(){
echo "Quack";
}
}
class MuteQuack implements QuackBehavior{
public function quack(){
echo "Silence";
}
}
class Squeak implements QuackBehavior{
public function quack(){
echo "Squeak";
}
}
abstract class Duck{
protected $quackBehavior;
protected $flyBehavior;
public function performQuack(){
$this->$quackBehavior->quack();
}
public function performFly(){
$this->$flyBehavior->fly();
}
abstract public function display();
public function swim(){
echo "All ducks float, even decoy";
}
}
class MallardDuck extends Duck{
public function __construct(){
$this->quackBehavior=new Quack();
$this->flyBehavior=new FlyWithWings();
}
public function display(){
echo "I am real Mallard duck!";
}
}
$mallard=new MallardDuck();
$mallard->performQuack();
$mallard->performFly();
?>
When I run I get the error "Undefined variable: quackBehavior" in line "$this->$quackBehavior->quack();" inside "abstract class Duck".
The error says it all
public function performQuack(){
$this->$quackBehavior->quack();
}
public function performFly(){
$this->$flyBehavior->fly();
}
should be
public function performQuack(){
$this->quackBehavior->quack();
}
public function performFly(){
$this->flyBehavior->fly();
}
$this->quackBehaviory refers to a property of your class.
$quackBehaviory means that it's a function scoped variable.
So to access the class property you need to use $this->quackBehaviory
Remove the $ from $this->$quackBehavior->quack(); and $this->$flyBehavior->fly(); i.e. infront of $quackBehavior and $flyBehavior
Should be like this....
$this->quackBehavior->quack(); //<--- Under your performQuack()
and
$this->flyBehavior->fly(); //<--- Under your performFly()
Related
trait TestTrait
{
public function matches()
{
}
}
class TestClassOne
{
public static function matches()
{
}
}
class TestClassTwo extends TestClassOne
{
use TestTrait {
matches as alternativeMatches;
}
public function run()
{
$this->alternativeMatches();
}
}
When calling the method run as seen above it will return the error :Fatal error: Cannot make static method matches non static
The classes are not written by me and the trait I have used in multiple other locations. A hell if I have to rewrite the trait .. or have to make a new one , just to make it work with this class.
Is there a way to make it work ?
Cheers
Well I made it work with a bit of a hack ... but I do not like it...
Someone has a nicer way of doing this ?
class TestClassTwo extends TestClassOne
{
use TestTrait {
matches as alternativeMatches;
}
public function run()
{
$this->alternativeMatches();
}
public static function matches()
{
parent::matches();
}
}
I was unsure what to call this so feel free to edit the title.
I am trying to create my own API. within this API there are certain objects these objects all extends the super class ApiObject:
class ApiObject {
protected $sqltemplate;
public function __construct($db){
$this->sqltemplate = new sqlTemplates($db);
}
protected function getTemplate(){
return $this->sqltemplate;
}
}
Now an example of the objects that extends this class is:
class Group extends ApiObject {
public function __construct(){
}
public function findByUserId(){
}
public function findByTeam(){
}
Now my question is as follow:
When i construct a type of the Group object is the ApiObject's contructor always called? and if so how does it pass the parameter $db to the constructor?
You have all the code, why don't you just try it?
<?php
class ApiObject {
public function __construct($db){
echo __METHOD__, "($db)\n";
}
}
class Group extends ApiObject {
public function __construct(){
echo __METHOD__, "\n";
}
}
new Group;
outputs
Group::__construct
This shows that the constructor of the parent object is not called automatically. You have to do this via parent::__construct($db) and add the $db parameter to the second constructor.
<?php
class ApiObject {
public function __construct($db){
echo __METHOD__, "($db)\n";
}
}
class Group extends ApiObject {
public function __construct($db){
echo __METHOD__, "\n";
parent::__construct($db);
}
}
new Group("db");
outputs
Group::__construct
ApiObject::__construct(db)
For a better understanding: Group::__construct overwrites the parent constructor, that's the reason you have to call it manually. If you don't specify a constructor, the parent constructor is called automatically. Example:
<?php
class ApiObject {
public function __construct($db){
echo __METHOD__, "($db)\n";
}
}
class Group extends ApiObject {
}
new Group("db");
outputs
ApiObject::__construct(db)
base class:
abstract class Challenge
{
abstract **static** public function getName();
}
now two classes from it:
class ChallengeType1 extends Challenge
{
public **static** function getName()
{
return 'Swimming';
}
}
class ChallengeType2 extends Challenge
{
public **static** function getName()
{
return 'Climbing';
}
}
as you all might know, we can't use static, but it would be reasonable. So I can't do like that: for example, I have the classname, so I want to know it's name: ChallengeType2::getName(); - it will fail! First I should construct the object - looks unnecessary (not to mention, what it this class have very complex initialization?)
Turns out you cannot have static abstract methods on an abstract class. See here:
Why does PHP 5.2+ disallow abstract static class methods?
But you can declare an interface to require a static method.
Here is an example that compiles:
Working Example
<?php
interface IChallenge
{
static function getName();
}
abstract class Challenge implements IChallenge
{
}
class ChallengeType1 extends Challenge
{
public static function getName()
{
return 'Swimming';
}
}
class ChallengeType2 extends Challenge
{
public static function getName()
{
return 'Climbing';
}
}
How can I prevent the something method below to be created in the foo class ?
class fooBase{
public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
Use the final keyword (like in Java etc):
class fooBase{
final public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
See PHP Final keyword. Note that foo will still have a method something, but something will only come from fooBase and foo can't override it.
Use the final keyword.
In your parent:
final public function something()
You can use final to prevent base methods being overwritten.
class fooBase{
final public function something(){
}
}
I'd like to start by showing a test case:
class A {
public static $instance=null;
public function __construct(){
self::$instance=$this;
}
public function className(){
return get_class(self::$instance);
}
}
class B extends A {
public function className(){
return get_class(self::$instance);
}
}
// test code
$b=new B();
echo $b->className; // B
$a=new A();
echo $a->className; // A
echo $b->className; // A <- error: not B any more!
Notes
I'm using a factory+singleton patterns above. Well, somewhat.
I don't need any specs on "implementing patterns correctly". I need problem solving, not KISS violations ;).
Critics might say A should be an interface. Ideally, that's what it should have been, but it's just a simple class, sorry.
The issues lies in the fact that self::$instance is the same for all instances. How do I separate self::$instance for each class?
Edit: I've had this idea:
$GLOBALS['store']=array();
class A {
public static $instance=null;
public function __construct(){
$GLOBALS['store'][__CLASS__]=$this;
}
}
You could store an instance per class name:
class A {
public static function getInstance(){
// Maybe use this function to implement the singleton pattern ...
return self::$instance[get_called_class()];
}
public function className(){
return get_class(self::getInstance());
}
}
You can not do this the clean way.
That is one of the mayor drawbacks on stati propertys: you cannot overrride them.
But you wantet an sollution so.....here is the worarround:
use __calllStatic
<?php
class A {
public static function __callstatic($name,$args)
{
if($name="getClass"){
return 'A';
}
}
}
class B extends A{
public static function __callstatic($name,$args)
{
if($name="getClass"){
return 'B';
}
}
}
echo A::getClass();
echo B::getClass();
?>
the output of this is "AB";
You can add a public static $instance=null; declaration in class B.
class A {
public static $instance=null;
public function __construct(){
self::$instance=$this;
}
public function className(){
return get_class(self::$instance);
}
}
class B extends A {
public static $instance=null;
public function className(){
return get_class(self::$instance);
}
}
// test code
$b=new B();
echo $b->className(); // B
$a=new A();
echo $a->className(); // A
echo $b->className(); // Now returns B, as desired.