Today i was reading design pattern and i tried to make a sample program which consist of a interface, two class which implement that interface and a main index class.let have a look at the code given below.
firstly the interface Iproduct
<?php
interface Iproduct
{
//Define the abstract method
public function apple();
public function mango();
}
the two class which implement the interface
<?php
// Including the interface
include_once 'Iproduct.php';
class Apple implements Iproduct
{
public function apple()
{
echo ("We sell apples!");
}
public function mango()
{
echo ("We do not sell Mango!");
}
}
<?php
// Include the interface Iprodduct
include_once 'Iproduct.php';
class Mango implements Iproduct
{
public function apple()
{
echo ("We do not sell Apple");
}
public function mango()
{
echo ("We sell mango!");
}
}
now the main class
<?php
include_once ('apple.php');
include_once ('Mango.php');
class UserProduct
{
public function __construct()
{
$apple_class_obj=new Apple();
$mango_class_obj=new Mango();
//echo("<br/> the apple class object: ".$apple_class_obj);
}
}
//creating the object of the UserProduct
echo ("creating the object!<br/>");
$userproduct_obj=new UserProduct();
?>
the output which i get when i execute the code is:
creating the object!
we sell apples!we sell mango
now the problem is that i am unable to get that how is the second output ie, we sell apple! and we sell mango! is being displayed.please let me know the reason
In the past (PHP before version 5), the method with the same name as the class is called when the object is created (PHP old-style constructor methods).
Because PHP is backwards compatible to that behavior, you see the output now.
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics. [Bold by me]
From: Constructors and Destructors in the PHP Manual
So what you experience is less a problem with the interface or the objects per-se, it's just some side-effect you're likely not aware of (this is really old).
To work around that, just implement a __construct() method in both classes so that the old-style constructor is not called any longer:
class Mango implements Iproduct
{
public function __construct() {}
...
An empty method per class is enough here to stop that.
You might be as well interested in:
What is the function __construct() used for? (Jan 2009)
Why are functions and methods in PHP case-insensitive? (May 2010)
Why is my constructor still called even if the class and constructor case are different? (Oct 2011)
in php 4x a method with the same name as the class was considered as the constructor. With php 5x the constructor is explicitly named __construct.
Your experiencing the outcome due to backward compatibility of PHP.
Related
I have the following OOP structure:
<?php
interface AnimalInterface
{
public function getName();
}
class Dog implements AnimalInterface
{
public function getName() {
return 'dog';
}
public function makeFriends()
{
echo 'I have friends now :)';
}
}
class Cat implements AnimalInterface
{
public function getName() {
return 'cat';
}
public function hateFriends()
{
echo 'I cant make friends :(';
}
}
interface AnimalDoInterface
{
public function makeFriend(AnimalInterface $animal);
}
class DogFriend implements AnimalDoInterface
{
public function makeFriend(Dog $dog)
{
$dog->makeFriends();
}
}
class CatFriend implements AnimalDoInterface
{
public function makeFriend(Cat $cat)
{
$cat->hateFriends();
}
}
Now PHP's manual on Object Interfaces says:
The class implementing the interface must use the exact same method signatures as are defined in the interface. Not doing so will result in a fatal error.
Why is this the case? Am I misunderstanding interfaces completely? Surely I should be able to declare AnimalDoInterface::makeFriend with anything that is the interface or an implementation of that interface? In this case it should technically be compatible as Cat implements AnimalInterface, which is what it's expecting.
Regardless of whether I am getting my OOP wrong, is there a way to implement this in PHP?
So it seems I wasn't clear enough, my bad for that. However, basically what I'm trying to achieve is to have the implementations of AnimalDoInterface to be more restrictive than it's interface says. So in this case, I'd like DogFriend::makeFriend to only allow the Dog class as it's argument, which in my mind should be acceptable as it implements the AnimalInterface, and the CatFriend to allow a Cat class, which again, same thing.
EDIT: fixed the classes, also added what I'm trying to achieve.
EDIT 2:
So at the moment, the way I'd have to implement it is as following:
class DogFriend implements AnimalDoInterface
{
public function makeFriend(AnimalInterface $dog)
{
if(!($dog instanceof Dog)) {
throw new \Exception('$dog must be of Dog type');
}
$dog->makeFriends();
}
}
class CatFriend implements AnimalDoInterface
{
public function makeFriend(AnimalInterface $cat)
{
if(!($dog instanceof Cat)) {
throw new \Exception('$dog must be of Cat type');
}
$cat->hateFriends();
}
}
I'd like to have to avoid this extra check for the class type.
An interface's only job is to enforce the fact that two objects behave in an identical way, regardless of how they implement that behaviour. It is a contract stating that two objects are interchangeable for certain specific purposes.
(Edit: This part of the code has been corrected, but serves as a good introduction.) The interface AnimalInterface defines the behaviour (function) getAnimalName(), and any class claiming to implement that interface must implement that behaviour. class Dog is declared with implements AnimalInterface, but doesn't implement the required behaviour - you can't call getAnimalName() on instances of Dog. So we already have a fatal error, as we have not met the "contract" defined by the interface.
Fixing that and proceeding, you then have an interface AnimalDoInterface which has the defined behaviour (function) of makeFriend(AnimalInterface $animal) - meaning, you can pass any object which implements AnimalInterface to the makeFriend method of any object which implements AnimalDoInterface.
But you then define class DogFriend with a more restrictive behaviour - its version of makeFriend can only accept Dog objects; according to the interface it should also be able to accept Cat objects, which also implement AnimalInterface, so again, the "contract" of the interface is not met, and we will get a fatal error.
If we were to fix that, there is a different problem in your example: you have a call to $cat->hateFriends(); but if your argument was of type AnimalInterface or AnimalDoInterface, you would have no way to know that a hateFriends() function existed. PHP, being quite relaxed about such things, will let you try that and blow up at runtime if it turns out not to exist after all; stricter languages would only let you use functions that are guaranteed to exist, because they are declared in the interface.
To understand why you can't be more restrictive than the interface, imagine you don't know the class of a particular object, all you know is that it implements a particular interface.
If I know that object $a implements AnimalInterface, and object $b implements AnimalDoInterface, I can make the following assumptions, just by looking at the interfaces:
I can call $a->getName(); (because AnimalInterface has that in its contract)
I can call $b->makeFriend($a); (because AnimalDoInterface has in its contract that I can pass anything that implements AnimalInterface)
But with your code, if $a was a Cat, and $b was a DogFriend, my assumption #2 would fail. If the interface let this happen, it wouldn't be doing its job.
The reason all classes implementing an interface must have the same methods is so that you can call that method on the object regardless of which subtype is instantiated.
In this case, you have a logical inconsistency because two subtypes, Cat and Dog, have different methods. So you can't call makeFriends() on the object, because you don't know that the object has that method.
That's the point of using interfaces, so you can use different subtypes, but at the same time you can be sure of at least some common methods.
One way to handle this in your case is to make sure Cat implements the same method, but make the method throw an exception at runtime, indicating that it's not possible. This allows the interface to be satisfies at compile time (I know PHP doesn't have a compiler, but this is mimicking languages like Java that do the interface checking at compile time).
class Cat implements AnimalInterface
{
public function makeFriends()
{
throw new RuntimeException('I cant make friends :(');
}
}
A class which implements AnimalDoInterface must have a makeFriend method which takes any object which implements AnimalInterface. In your case, trying to declare
class DogFriend implements AnimalDoInterface {
public function makeFriend(Dog $foo) { }
}
will not accurately implement this, since it should always be safe to pass anything which implements AnimalInterface to the makeFriend method of anything which implements AnimalDoInterface.
Hi I have a very simple class that implements an interface. Both the class and the interface are in the same file.
When I implement the interface I get a fatal error "Class not found", but when I remove the implements and then try to use the class I can use it fine???
Can anyone offer any advice on this?
Sorry here is some code that I am using to test at the moment:
$tester = new TypeOneTester();
$tester->test("Hello");
interface iTestInterface
{
public function test($data);
}
class TypeOneTester implements iTestInterface
{
public function test($data)
{
return $data;
}
}
Create an instance of your class after the class and the interface are defined, not before.
The order of definition in this case should be:
Interface
Class
Instance of Class (objects)
This is a (very poorly) documented limitation:
http://php.net/manual/pl/migration5.incompatible.php
In some cases classes must be declared before use. It only happens if some of the new features of PHP 5 (such as interfaces) are used. Otherwise the behaviour is the old.
I've filed a bug report nonetheless. IMO it should be fixed as it's inconsistent behaviour and the error message is not helpful for anyone who assumes as I did that PHP simply didn't care where you declare functions/classes. Come on, it's been there for over 10 years now...
https://bugs.php.net/bug.php?id=69665
smells like a bug in php. Make sure it's reproducible with the latest version and post to bugs.php.net.
Reproduce code
interface I {}
$a = new A;
$b = new B;
class A {
function __construct() { echo 'A'; }
}
class B implements I {
function __construct() { echo 'B'; }
}
Expected
AB
Actual:
A
Fatal error: Class 'B' not found...
That is because, php loading interface, and instantiate class class class object where there is a certain order and must be in a Php file, if the file is not in accordance with an order of 1. Require_one interface, 2. Require_one class
I have recently started php and was wondering the differences between __construct() and having a method with the same name as the class?
Is there a reason for using it? All I can work out is it overrides the method named Foo or is it down to which you prefer?
E.g.
class Foo {
function Foo()
{
echo 'Foo stated<br>';
}
function __construct() {
echo 'Construct started<br>';
}
}
Thanks
Using __construct() is the newer PHP5 more OOP focused method to call a constructor. Using a method with the same name as the class is the old deprecated way to do it, and it will not function as a constructor as of PHP 5.3.3 for namespaced classes.
From the constructors and destructors page:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.
Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is overridden with different parameters than the parent __construct() method has.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
"if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics."
Source: http://www.php.net/manual/en/language.oop5.decon.php
Foo() is a php4 way(deprecated), __construct() is php5 way. php will first look for __construct, then, if it's not found, it will use Foo
Is there a reason for using it? All I
can work out is it overrides the
method named Foo or is it down to
which you prefer?
The benefits of __construct() become clearer when you involve renaming and inheritance. If you rename a class, you then have to rename it's constructor. No big deal, but if class B inherits from class A you could end up with:
class B extends A {
function B() {
parent::A();
}
}
It's much easier and more maintainable to do:
function __construct() {
parent::__construct();
}
Now when you rename class A, you don't have to remember to also change the parent calls in all its children. Granted, there's still renaming to do in your code but at least this is not one of them.
Having a method with the same name as the class, which is automatically called as a constructor is a throwback to PHP4, and is to be considered deprecated... in the latest development branch of PHP, it will be treated as a normal class method. __construct is the formally accepted constructor in PHP5, although in current releases it will fall back to the PHP4 method if __construct doesn't exist.
I am getting started with OO PHP, and after reviewing a variety of classes which I have downloaded from the internet, I have noticed that some - but not all - of these classes have an intial function with the same name e.g.
class MyClass{
function MyClass{
//function contents in here
}
function otherfunction{
//more stuff here
}
}
What is this inital function for? And how does it help with writing classes?
It's an old-style constructor. If you are using PHP 5 (you ought to), you should avoid those constructors and do instead:
class MyClass{
function __construct() {
//function contents in here
}
function otherfunction() {
//more stuff here
}
}
Constructors are, in short, used to run initialization code and enforce class invariants.
it is a constructor - anything put in here is executed when the object is instantiated
That function is a constructor. It is used for initializing the object.
Constructor
please also note that it's case insensitive. For example whan you have a Bark() class for a dog game the class name Bark is your reference to the noise that a dog makes.
If you want a specifig dog (e.g. a poodle which extends a general Dog pbject) to bark, you could name that method bark(), because that's what you want the dog to do (see the duality between the THING and the COMMAND ? (Bark class and bark() method) ).
So, when you do this:
interface BarkBehaviour
{
public function bark();
}
class Bark implements BarkBehaviour
{
public function bark()
{
echo "\nWoof!";
}
}
the instantiation of the barkBehaviour property of your dog will echo "Woof", because PHP thinks that the bark() method is the constructor for the Bark class, which you did NOT intend that way. In JAVA these things are case sensitive so the Bark classes constructor must be called Bark(), not bark().
Below is an example class hierarchy and code. What I'm looking for is a way to determine if 'ChildClass1' or 'ChildClass2' had the static method whoAmI() called on it without re-implementing it in each child class.
<?php
abstract class ParentClass {
public static function whoAmI () {
// NOT correct, always gives 'ParentClass'
$class = __CLASS__;
// NOT correct, always gives 'ParentClass'.
// Also very round-about and likely slow.
$trace = debug_backtrace();
$class = $trace[0]['class'];
return $class;
}
}
class ChildClass1 extends ParentClass {
}
class ChildClass2 extends ParentClass {
}
// Shows 'ParentClass'
// Want to show 'ChildClass1'
print ChildClass1::whoAmI();
print "\n";
// Shows 'ParentClass'
// Want to show 'ChildClass2'
print ChildClass2::whoAmI();
print "\n";
I believe what you're referring to is a known php bug. Php 5.3 is aiming to address this issue with a new Late Static Binding feature.
http://www.colder.ch/news/08-24-2007/28/late-static-bindings-expl.html
Now that PHP 5.3 is widely available in the wild, I wanted to put together a summary answer to this question to reflect newly available techniques.
As mentioned in the other answers, PHP 5.3 has introduced Late Static Binding via a new static keyword. As well, a new get_called_class() function is also available that can only be used within a class method (instance or static).
For the purpose of determining the class as was asked in this question, the get_called_class() function is appropriate:
<?php
abstract class ParentClass {
public static function whoAmI () {
return get_called_class();
}
}
class ChildClass1 extends ParentClass {
}
class ChildClass2 extends ParentClass {
}
// Shows 'ChildClass1'
print ChildClass1::whoAmI();
print "\n";
// Shows 'ChildClass2'
print ChildClass2::whoAmI();
print "\n";
The user contributed notes for get_called_class() include a few sample implementations that should work in PHP 5.2 as well by making use of debug_backtrace().
Class identification is often a symptom of not well understood Polymorphism.
The clients of ChildClass1 and ChildClass2 shouldn't need to distinguish between them.
There's no place where any class should ask about someObject.whoAmI().
Whenever you have the urge to write if someObject.whoAmI() == 'ChildClass1' { do X(someObject) } you should really add an X() method to the ParentClass with various implementations in the various ChildClasses.
This kind of "run-time type identification" can almost always be replaced with properly polymorphic class designs.
As of PHP 5.3 it'll be possible with the use of the static keyword, but for now it isn't possible.
No. Wait for PHP 5.3.