I am trying to make abstract method clear to me , so I wrote this code and test it. But when I run it the following error appear :
Fatal error: Class Book contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Book::ClassName) in C:\AppServ\www\index2.php on line 5
so where is the problem and why ?
<?php
class Book
{
abstract public function ClassName();
}
class firstBook extends Book{
public function ClassName()
{
echo "Called form class firstBook";
}
}
class secondBook extends Book{
public function ClassName()
{
echo "Called from class secondBook";
}
}
$o = new firstBook();
$o2 = new secondBook();
$o->Classname();
$o2->Classname();
?>
Class must also use abstract keyword
<?php
abstract class Book
{
abstract public function ClassName();
}
class firstBook extends Book{
public function ClassName()
{
echo "Called form class firstBook";
}
}
class secondBook extends Book{
public function ClassName()
{
echo "Called from class secondBook";
}
}
You cannot declare abstract function in a concrete class. Update your Book class to be abstract.
abstract class Book
{
abstract public function ClassName();
}
You class has to be abstract.
Change
class Book
to
abstract class Book
Also, you are calling the functions wrongly.
Replace
$o->Classname;
$o2->Classname;
to
$o->ClassName();
$o2->ClassName();
Putting it all together
<?php
abstract class Book
{
abstract public function ClassName();
}
class firstBook extends Book{
public function ClassName()
{
echo "Called form class firstBook";
}
}
class secondBook extends Book{
public function ClassName()
{
echo "Called from class secondBook";
}
}
$o = new firstBook;
$o2 = new secondBook;
$o->ClassName();
$o2->ClassName();
?>
OUTPUT :
Called form class firstBookCalled from class secondBook
Related
I learned that I can use a parent's constructor in PHP with ParentClass::__construct();.
I imagine it's not possible, but I want to be sure; can I override or remove an aspect of the copied constructor? In other words, if the parent's constructor was
public function __construct(){
print "This is from the parent class";
test();
}
public function test(){
print "Remove this function when copying to child class";
}
is there any way that I can
public function __construct(){
ParentClass::__construct();
//override/remove/negate test() function in the copied construct.
}
Right now, your object structure is like this:
class ParentClass {
public function test(): void {}
}
class ChildClass extends ParentClass {
// This class has access to test() through inheritance
}
What you could have instead:
class BaseClass {
// Here, have everything that's actually common between all subclasses
}
class ClassA extends BaseClass {
public function test(): void {}
}
class ClassB extends BaseClass {
// This class does not have access to test()
}
You could also mix in some interfaces, but that's the basic idea.
Assume I have this interface...
interface Foo {
public function bar();
public function nothing();
}
I'm tasked with writing an "abstract class that also abstracts the methods", and I just want to make sure that I'm writing this correctly. My code is as follows...
abstract class Bar implements Foo {
abstract public function bar();
abstract public function nothing();
}
Is this the correct way of doing this?
You don't need to implement the interface in your abstract class. Your abstract class provides an interface like contract to classes that extend it.
abstract class Bar {
abstract public function bar();
abstract public function nothing();
public function concreteMethod() {
print "I can do this in an abstract class";
}
}
class Concrete extends Bar {
public function bar() {
print "in bar";
}
public function nothing() {
//nothing
}
}
If you do not have any need to implement some shared (by all subclasses) functionality in the abstract class, you should better derive directly from the interface, to make things not unnecessarily complicated.
In this case, the whole thing could be sensefully simplyfied to:
<?php
interface Foo
{
public function bar();
public function nothing();
}
class C implements Foo
{
public function bar() {
echo 'bar';
}
public function nothing() {
echo 'nothing';
}
}
$obj = new C();
$obj->bar();
?>
Read more at:
Is it good or bad for an abstract class to implement an interface?
I don't know, but one chance is that create abstract class with implements interface like this.
interface Foo {
public function bar();
public function nothing();
}
abstract class Bar implements Foo {
public function bazz() {
echo ' Bye';
}
}
class Test extends Bar {
public function bar()
{
echo 'Hello ';
}
public function nothing()
{
echo 'World';
}
}
By this you have your abstract class having abstract methods from a interface. It also used in some architecture design where you want a parent class as abstract class but define all abstract methods in interface.
I would like to do something like this:
abstract class Foo
{
public function __construct()
{
echo 'This is the parent constructor';
}
abstract function __construct();
}
class Bar extends Foo
{
// constructor is required as this class extends Foo
public function __construct()
{
//call parent::__construct() if necessary
echo 'This is the child constructor';
}
}
But I get a fatal error when doing this:
Fatal error: Cannot redeclare Foo::__construct() in Foo.php on line 8
Is there another way to ensure child classes have a constructor?
In short no. Non of the magic methods can be declared via the abstract keyword.
If you want to use the old way of constructors, create a method with the same name as the class, and declare it abstract. This will be called upon instantiation of the class.
Example:
abstract class Foo
{
public function __construct()
{
echo 'This is the parent constructor';
}
abstract function Bar();
}
class Bar extends Foo
{
// constructor is required as this class extends Foo
public function Bar()
{
parent::__construct();
echo 'This is the child constructor';
}
}
I would suggest the use of interfaces for your functionality though.
Why does this abstract class not work and output nothing?
<?php
abstract class Con {
function __construct($name);
}
}
class Shop extends Con {
function __construct($name) {
$this->shopname = $name;
}
function write() {
echo $this->shopname;
}
function outputdate() {
echo ' ' . date('Y');
}
function __destruct() {
$this->outputdate();
}
}
You cannot define some class in other class body. Instead, you must use PHP OOP features to extend one class from another.
class Shop extends Con{
...code goes here....
}
$shop = new Shop('shopname');
$shop->write();
You can't instantiate an abstract class. Also, you can't create a class within another class.
http://php.net/manual/en/language.oop5.abstract.php
http://en.wikipedia.org/wiki/Abstract_type
Check out this link if you are looking to subclass.
http://php.net/manual/en/keyword.extends.php
I think there is a problem in php's OOP implementation.
EDIT: Consider more illustrative example:
abstract class Animal {
public $name;
// public function Communicate(Animal $partner) {} // Works
public abstract function Communicate(Animal $partner); // Gives error
}
class Panda extends Animal {
public function Communicate(Panda $partner) {
echo "Hi {$partner->name} I'm a Panda";
}
}
class Human extends Animal {
public function Communicate(Human $partner) {
echo "Hi {$partner->name} I'm a Human";
}
}
$john = new Human(); $john->name = 'John';
$mary = new Human(); $mary->name = 'Mary';
$john->Communicate($mary); // should be ok
$zuzi = new Panda(); $zuzi->name = 'Zuzi';
$zuzi->Communicate($john); // should give error
The problem is that when Animal::Communicate is an abstract method, php tells that the following methods are illegal:
"public function Communicate(Panda $partner)"
"public function Communicate(Human $partner)"
but when Animal::Communicate is non-abstract but has zero-implementation Php thinks that these methods are legal. So in my opinion it's not right because we are doing override in both cases, and these both cases are equal, so it seems like it's a bug...
Older part of the post:
Please consider the following code:
Framework.php
namespace A
{
class Component { ... }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
Implementation.php
namespace B
{
class MyComponent extends \A\Component { ... }
}
MyDecorator.php
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\B\MyComponent $component) { ... }
}
}
The following code gives error in MyDecorator.php telling
Fatal error: Declaration of MyDecorator::Decorate() must be compatible with that of A\Decorator::Decorate() in MyDecorator.php on line ...
But when I change the Framework.php::Decorator class to the following implementation:
abstract class Decorator {
public function Decorate(\A\Component $component) {}
}
the problem disappears.
I'm not sure (haven't tested it ;), but you declare this abstract function:
public abstract function Decorate(\A\Component $component);
So you should implement this EXACTLY like that. But you did this:
public function Decorate(\B\MyComponent $component) { ... }
That's not the same. Could you try to change that to \A\Component?
To all comments: fact of the matter is that this piece of PHP "runs"
namespace A
{
class Component { }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
namespace B
{
class MyComponent extends \A\Component { }
}
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\A\Component $component) {}
}
}
And this doesn't:
<?php
namespace A
{
class Component { }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
namespace B
{
class MyComponent extends \A\Component { }
}
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\B\MyComponent $component) {}
}
}
?>
With this error: PHP Fatal error: Declaration of A\MyDecorator::Decorate() must be compatible with that of A\Decorator::Decorate() in line 18
Now you can discuss all you like about how that should or should not be, but that's the problem with the code.
so, to satisfy my own curiosity: this is illegal too:
<?php
class Component { }
abstract class Decorator {
public abstract function Decorate(Component $component);
}
class MyComponent extends Component { }
class MyDecorator extends Decorator {
public function Decorate(MyComponent $component) {}
}
?>
It's not the namespaces or anything. It just doesn't seem legal.
See http://bugs.php.net/bug.php?id=36601, this issues has been reported as a bug but was rejected because of laziness :D
It has nothing to do with it being abstract. It has to do with the type hinting. The two definitions of the method are not compatible because you explicitly set the argument to be of type \A\Component and then try to overload the method with \B\Component you cant do that because it changes the method signature. Any subsequent declaration of Decorate must use the same type hint as its parent declaration in order for the method signatures to be compatible.
This might assist someone, and am not late.
The best way to handle such is by using an interface.
Consider below;
<?php
interface Componentor{}
class Component implements Componentor { }
abstract class Decorator {
public abstract function Decorate(Componentor $component);
}
class MyComponent extends Component { }
class MyDecorator extends Decorator {
public function Decorate(Componentor $component) {}
}
?>
Usage;
<?php
$c=new Component();
//TODO ....blah blah blah...
$decor=new MyDecorator();
//TODO ....blah blah blah...
$decor->Decorate($c);
?>