What is an abstract class in PHP? - php

What is an abstract class in PHP?
How can it be used?

An abstract class is a class that contains at least one abstract method, which is a method without any actual code in it, just the name and the parameters, and that has been marked as "abstract".
The purpose of this is to provide a kind of template to inherit from and to force the inheriting class to implement the abstract methods.
An abstract class thus is something between a regular class and a pure interface. Also interfaces are a special case of abstract classes where ALL methods are abstract.
See this section of the PHP manual for further reference.

Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and require subclasses to provide implementations for the abstract methods.
1. Can not instantiate abstract class: Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract.
Example below :
abstract class AbstractClass
{
abstract protected function getValue();
abstract protected function prefixValue($prefix);
public function printOut() {
echo "Hello how are you?";
}
}
$obj=new AbstractClass();
$obj->printOut();
//Fatal error: Cannot instantiate abstract class AbstractClass
2. Any class that contains at least one abstract method must also be abstract: Abstract class can have abstract and non-abstract methods, but it must contain at least one abstract method. If a class has at least one abstract method, then the class must be declared abstract.
Note: Traits support the use of abstract methods in order to impose requirements upon the exhibiting class.
Example below :
class Non_Abstract_Class
{
abstract protected function getValue();
public function printOut() {
echo "Hello how are you?";
}
}
$obj=new Non_Abstract_Class();
$obj->printOut();
//Fatal error: Class Non_Abstract_Class contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Non_Abstract_Class::getValue)
3. An abstract method can not contain body: Methods defined as abstract simply declare the method's signature - they cannot define the implementation. But a non-abstract method can define the implementation.
abstract class AbstractClass
{
abstract protected function getValue(){
return "Hello how are you?";
}
public function printOut() {
echo $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
//Fatal error: Abstract function AbstractClass::getValue() cannot contain body
4. When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child :If you inherit an abstract class you have to provide implementations to all the abstract methods in it.
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
// Common method
public function printOut() {
print $this->getValue() . "<br/>";
}
}
class ConcreteClass1 extends AbstractClass
{
public function printOut() {
echo "dhairya";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
//Fatal error: Class ConcreteClass1 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AbstractClass::getValue)
5. Same (or a less restricted) visibility:When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private.
Note that abstract method should not be private.
abstract class AbstractClass
{
abstract public function getValue();
abstract protected function prefixValue($prefix);
public function printOut() {
print $this->getValue();
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."<br/>";
//Fatal error: Access level to ConcreteClass1::getValue() must be public (as in class AbstractClass)
6. Signatures of the abstract methods must match:When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child;the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. For example, if the child class defines an optional argument, where the abstract method's signature does not, there is no conflict in the signature.
abstract class AbstractClass
{
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "<br/>";
echo $class->prefixName("Pacwoman"), "<br/>";
//output: Mr. Pacman
// Mrs. Pacwoman
7. Abstract class doesn't support multiple inheritance:Abstract class can extends another abstract class,Abstract class can provide the implementation of interface.But it doesn't support multiple inheritance.
interface MyInterface{
public function foo();
public function bar();
}
abstract class MyAbstract1{
abstract public function baz();
}
abstract class MyAbstract2 extends MyAbstract1 implements MyInterface{
public function foo(){ echo "foo"; }
public function bar(){ echo "bar"; }
public function baz(){ echo "baz"; }
}
class MyClass extends MyAbstract2{
}
$obj=new MyClass;
$obj->foo();
$obj->bar();
$obj->baz();
//output: foobarbaz
Note: Please note order or positioning of the classes in your code can affect the interpreter and can cause a Fatal error.
So, when using multiple levels of abstraction, be careful of the positioning of the classes within the source code.
below example will cause Fatal error: Class 'horse' not found
class cart extends horse {
public function get_breed() { return "Wood"; }
}
abstract class horse extends animal {
public function get_breed() { return "Jersey"; }
}
abstract class animal {
public abstract function get_breed();
}
$cart = new cart();
print($cart->get_breed());

An abstract class is a class that is
only partially implemented by the
programmer. It may contain one or more
abstract methods. An abstract method
is simply a function definition that
serves to tell the programmer that the
method must be implemented in a child
class.
There is good explanation of that here.

Abstract Class
1. Contains an abstract method
2. Cannot be directly initialized
3. Cannot create an object of abstract class
4. Only used for inheritance purposes
Abstract Method
1. Cannot contain a body
2. Cannot be defined as private
3. Child classes must define the methods declared in abstract class
Example Code:
abstract class A {
public function test1() {
echo 'Hello World';
}
abstract protected function f1();
abstract public function f2();
protected function test2(){
echo 'Hello World test';
}
}
class B extends A {
public $a = 'India';
public function f1() {
echo "F1 Method Call";
}
public function f2() {
echo "F2 Method Call";
}
}
$b = new B();
echo $b->test1() . "<br/>";
echo $b->a . "<br/>";
echo $b->test2() . "<br/>";
echo $b->f1() . "<br/>";
echo $b->f2() . "<br/>";
Output:
Hello World
India
Hello World test
F1 Method Call
F2 Method Call

Abstract Class contains only declare the method's signature, they can't define the implementation.
Abstraction class are defined using the keyword abstract .
Abstract Class is not possible to implement multiple inheritance.
Latest version of PHP 5 has introduces abstract classes and methods.
Classes defined as abstract , we are unable to create the object ( may not instantiated )

An abstract class is like the normal class it contains variables it contains protected variables functions it contains constructor only one thing is different it contains abstract method.
The abstract method means an empty method without definition so only one difference in abstract class we can not create an object of abstract class
Abstract must contains the abstract method and those methods must be defined in its inheriting class.

Related

PHP: Fatal error: Cannot instantiate abstract class

I have an abstract database class named as:
abstract class database {
protected $value;
}
I created another abstract class
abstract class my_database extends database {
public function set_value($value) {
$this->value = $value;
}
}
When I try to use it:
$my_db = new my_database();
I get error:
Fatal error: Cannot instantiate abstract class my_database in ...
What I try to do is: The abstract class database has a protected $value and I would like to create a wrapper class, to be able to change the protected value (temporarily).
How can I do that?
EDIT1: unfortunately earlier, when I tried without abstract my_database, I got the errors:
- abstract methods and must therefore be declared abstract or implemented
- Abstract function cannot contain body
EDIT2:
After taking out the abstract word completely from my_database, I got the following error:
Fatal error: Class my_database contains 32 abstract methods and must
therefore be declared abstract or implement the remaining methods
How can I fix this?
Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract. You can read about this in PHP's documentation here: link
Here's an example.
There is an abstract class (note that abstract methods don't have body - they CAN'T have body - it's just a signature):
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Common method. It will be available for all children - they don't have to declare it again.
public function printOut() {
print $this->getValue() . "\n";
}
}
Extend your abstract class with a class like this (note that all abstract methods MUST be defined in concrete class):
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
Then you can create instance of ConcreteClass1:
$class1 = new ConcreteClass1;
Your class should not be abstract:
class my_database extends database {
public function set_value($value) {
$this->value = $value;
}
}
In OOP, abstract class can't be instanciated juste it can be extended.

Can It be possible to have private concrete method inside abstract class in Php.

Can It be possible to have a private concrete method inside the abstract class in Php
TL;DR: yes, you can.
abstract class Foo
{
private function test() {
echo 'abstract private' . PHP_EOL;
}
public function useTest() {
$this->test();
}
}
class Bar extends Foo {}
$x = new Bar;
$x->useTest();
Live example: https://3v4l.org/Efd5Q
But that private method will be visible ONLY to that abstract class. It means, that it will have to be used by some other concrete method within the abstract class (with protected of public visibility).
The child classes won't be able to call it directly.

How to implement abstract properties in PHP? [duplicate]

Is there any way to define abstract class properties in PHP?
abstract class Foo_Abstract {
abstract public $tablename;
}
class Foo extends Foo_Abstract {
//Foo must 'implement' $property
public $tablename = 'users';
}
There is no such thing as defining a property.
You can only declare properties because they are containers of data reserved in memory on initialization.
A function on the other hand can be declared (types, name, parameters) without being defined (function body missing) and thus, can be made abstract.
"Abstract" only indicates that something was declared but not defined and therefore before using it, you need to define it or it becomes useless.
No, there is no way to enforce that with the compiler, you'd have to use run-time checks (say, in the constructor) for the $tablename variable, e.g.:
class Foo_Abstract {
public final function __construct(/*whatever*/) {
if(!isset($this->tablename))
throw new LogicException(get_class($this) . ' must have a $tablename');
}
}
To enforce this for all derived classes of Foo_Abstract you would have to make Foo_Abstract's constructor final, preventing overriding.
You could declare an abstract getter instead:
abstract class Foo_Abstract {
abstract public function get_tablename();
}
class Foo extends Foo_Abstract {
protected $tablename = 'tablename';
public function get_tablename() {
return $this->tablename;
}
}
Depending on the context of the property, if I want to force declaration of an abstract class property in an extended class, I like to use a constant with the static keyword for the property in the abstract object constructor or setter/getter methods. You can optionally use final to prevent the method from being overridden in extended classes.
Example: https://3v4l.org/WH5Xl
abstract class AbstractFoo
{
public $bar;
final public function __construct()
{
$this->bar = static::BAR;
}
}
class Foo extends AbstractFoo
{
//const BAR = 'foobar'; //uncomment to prevent exception
}
$foo = new Foo();
//Fatal Error: Undefined class constant 'BAR'
However, the extended class overrides the parent class properties and methods if redefined.
For example; if a property is declared as protected in the parent and redefined as public in the extended class, the resulting property is public. Otherwise, if the property is declared private in the parent it will remain private and not available to the extended class.
http://www.php.net//manual/en/language.oop5.static.php
As stated above, there is no such exact definition.
I, however, use this simple workaround to force the child class to define the "abstract" property:
abstract class Father
{
public $name;
abstract protected function setName(); // now every child class must declare this
// function and thus declare the property
public function __construct()
{
$this->setName();
}
}
class Son extends Father
{
protected function setName()
{
$this->name = "son";
}
function __construct(){
parent::__construct();
}
}
The need for abstract properties can indicate design problems. While many of answers implement kind of Template method pattern and it works, it always looks kind of strange.
Let's take a look at the original example:
abstract class Foo_Abstract {
abstract public $tablename;
}
class Foo extends Foo_Abstract {
//Foo must 'implement' $property
public $tablename = 'users';
}
To mark something abstract is to indicate it a must-have thing. Well, a must-have value (in this case) is a required dependency, so it should be passed to the constructor during instantiation:
class Table
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function name(): string
{
return $this->name;
}
}
Then if you actually want a more concrete named class you can inherit like so:
final class UsersTable extends Table
{
public function __construct()
{
parent::__construct('users');
}
}
This can be useful if you use DI container and have to pass different tables for different objects.
I've asked myself the same question today, and I'd like to add my two cents.
The reason we would like abstract properties is to make sure that subclasses define them and throw exceptions when they don't. In my specific case, I needed something that could work with statically.
Ideally I would like something like this:
abstract class A {
abstract protected static $prop;
}
class B extends A {
protected static $prop = 'B prop'; // $prop defined, B loads successfully
}
class C extends A {
// throws an exception when loading C for the first time because $prop
// is not defined.
}
I ended up with this implementation
abstract class A
{
// no $prop definition in A!
public static final function getProp()
{
return static::$prop;
}
}
class B extends A
{
protected static $prop = 'B prop';
}
class C extends A
{
}
As you can see, in A I don't define $prop, but I use it in a static getter. Therefore, the following code works
B::getProp();
// => 'B prop'
$b = new B();
$b->getProp();
// => 'B prop'
In C, on the other hand, I don't define $prop, so I get exceptions:
C::getProp();
// => Exception!
$c = new C();
$c->getProp();
// => Exception!
I must call the getProp() method to get the exception and I can't get it on class loading, but it is quite close to the desired behavior, at least in my case.
I define getProp() as final to avoid that some smart guy (aka myself in 6 months) is tempted to do
class D extends A {
public static function getProp() {
// really smart
}
}
D::getProp();
// => no exception...
As you could have found out by just testing your code:
Fatal error: Properties cannot be declared abstract in ... on line 3
No, there is not. Properties cannot be declared abstract in PHP.
However you can implement a getter/setter function abstract, this might be what you're looking for.
Properties aren't implemented (especially public properties), they just exist (or not):
$foo = new Foo;
$foo->publicProperty = 'Bar';
PHP 7 makes it quite a bit easier for making abstract "properties". Just as above, you will make them by creating abstract functions, but with PHP 7 you can define the return type for that function, which makes things a lot easier when you're building a base class that anyone can extend.
<?php
abstract class FooBase {
abstract public function FooProp(): string;
abstract public function BarProp(): BarClass;
public function foo() {
return $this->FooProp();
}
public function bar() {
return $this->BarProp()->name();
}
}
class BarClass {
public function name() {
return 'Bar!';
}
}
class FooClass extends FooBase {
public function FooProp(): string {
return 'Foo!';
}
public function BarProp(): BarClass {
// This would not work:
// return 'not working';
// But this will!
return new BarClass();
}
}
$test = new FooClass();
echo $test->foo() . PHP_EOL;
echo $test->bar() . PHP_EOL;
if tablename value will never change during the object's lifetime, following will be a simple yet safe implementation.
abstract class Foo_Abstract {
abstract protected function getTablename();
public function showTableName()
{
echo 'my table name is '.$this->getTablename();
}
}
class Foo extends Foo_Abstract {
//Foo must 'implement' getTablename()
protected function getTablename()
{
return 'users';
}
}
the key here is that the string value 'users' is specified and returned directly in getTablename() in child class implementation. The function mimics a "readonly" property.
This is fairly similar to a solution posted earlier on which uses an additional variable. I also like Marco's solution though it can be a bit more complicated.
Just define the property in the base class without assigning it a (default) value.
Getting the property value without redefining it with a default value or assigning it a value will throw an Error.
<?php
class Base {
protected string $name;
public function i_am() : string {
return $this->name;
}
}
class Wrong extends Base {
...
}
class Good extends Base {
protected string $name = 'Somebody';
}
$test = new Good();
echo $test->i_am(), '<br>'; // Will show "Nobody"
$test = new Wrong();
echo $test->i_am(), '<br>'; // Will throw an Error:
// Error: Typed property Base::$name must not be accessed before initialization in ....
?>
You can define a static property in an abstract class.
<?php
abstract class Foo {
private static $bar = "1234";
public static function func() {
echo self::$bar;
}
}
Foo::func(); // It will be printed 1234
Too late to answer the question, but you may use the difference between self and static as follows
<?php
class A { // Base Class
protected static $name = 'ClassA';
public static function getSelfName() {
return self::$name;
}
public static function getStaticName() {
return static::$name;
}
}
class B extends A {
protected static $name = 'ClassB';
}
echo A::getSelfName(); // ClassA
echo A::getStaticName(); // ClassA
echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB

Analyze abstract class in php

i have become a bit confused about abstract class ! i have read more of the post written in stackoverflow and another website but i didn't understand ! so i took a look at my book again but i didn't understand it either . so please analyze the code below step by step :
thanks in advance
<?php
abstract class AbstractClass
{
abstract protected function getValue();
public function printOut() {
print $this->getValue();
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
$class2 = new ConcreteClass2;
$class2->printOut();
?>
By definition
'An abstract class is a class that is declared abstract —it may or may
not include abstract methods. Abstract classes cannot be instantiated,
but they can be subclassed. An abstract method is a method that is
declared without an implementation'.
If defined an abstract class, you should extend that class with another.
In case of having abstract methods within the abstract class, you should write them in the child class in order to instantiate the child.
Related to the code, that is why when you instantiate the ConcreteClass, the getValue function is 'overwritten' to the pattern, while calling to the printOut method is from the father itself, because It is already written and not overwritten by the child. (See also that method was not abstract, that is why you can also use it from the father class)
Your code is right. Abstact class mean, when you can not make a instance of it. You can not do this:
$abstract = new AbstractClass();

How to declare abstract method in non-abstract class in PHP?

class absclass {
abstract public function fuc();
}
reports:
PHP Fatal error: Class absclass
contains 1 abstract method and must
therefore be declared abstract or
implement the remaining methods
(absclass::fuc)
I want to know what it means by implement the remaining methods,how?
See the chapter on Class Abstraction in the PHP manual:
PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method's signature - they cannot define the implementation.
It means you either have to
abstract class absclass { // mark the entire class as abstract
abstract public function fuc();
}
or
class absclass {
public function fuc() { // implement the method body
// which means it won't be abstract anymore
};
}
I presume that remaining methods actually refers to the abstract methods you're trying to define (in this case, fuc()), since the non-abstract methods that might exist are okay anyway. It's probably an error message that could use a more precise wording: where it says remaining it could have said abstract.
The fix is pretty straightforward (that part of the error message is fine): you need to change this:
abstract public function fuc();
... into a proper implementation:
public function fuc(){
// Code comes here
}
... or, alternatively and depending your needs, make the whole class abstract:
abstract class absclass {
abstract public function fuc();
}
An abstract class cannot be directly instantiated, but it can contain both abstract and non-abstract methods.
If you extend an abstract class, you have to either implement all its abstract functions, or make the subclass abstract.
You cannot override a regular method and make it abstract, but you must (eventually) override all abstract methods and make them non-abstract.
<?php
abstract class Dog {
private $name = null;
private $gender = null;
public function __construct($name, $gender) {
$this->name = $name;
$this->gender = $gender;
}
public function getName() {return $this->name;}
public function setName($name) {$this->name = $name;}
public function getGender() {return $this->gender;}
public function setGender($gender) {$this->gender = $gender;}
abstract public function bark();
}
// non-abstract class inheritting from an abstract class - this one has to implement all inherited abstract methods.
class Daschund extends Dog {
public function bark() {
print "bowowwaoar" . PHP_EOL;
}
}
// this class causes a compilation error, because it fails to implement bark().
class BadDog extends Dog {
// boom! where's bark() ?
}
// this one succeeds in compiling,
// it's passing the buck of implementing it's inheritted abstract methods on to sub classes.
abstract class PassTheBuckDog extends Dog {
// no boom. only non-abstract subclasses have to bark().
}
$dog = new Daschund('Fred', 'male');
$dog->setGender('female');
print "name: " . $dog->getName() . PHP_EOL;
print "gender: ". $dog->getGender() . PHP_EOL;
$dog->bark();
?>
That program bombs with:
PHP Fatal error: Class BadDog
contains 1 abstract method and must
therefore be declared abstract or
implement the remaining methods
(Dog::bark)
If you comment out the BadDog class, then the output is:
name: Fred
gender: female
bowowwaoar
If you try to instantiate a Dog or a PassTheBuckDog directly, like this:
$wrong = new Dog('somma','it');
$bad = new PassTheBuckDog('phamous','monster');
..it bombs with:
PHP Fatal error: Cannot instantiate
abstract class Dog
or (if you comment out the $wrong line)
PHP Fatal error: Cannot instantiate
abstract class PassTheBuckDog
You can, however, call a static function of an abstract class:
abstract class Dog {
..
public static function getBarker($classname, $name, $gender) {
return new $classname($name, $gender);
}
..
}
..
$other_dog = Dog::getBarker('Daschund', 'Wilma', 'female');
$other_dog->bark();
That works just fine.
You're being slightly led astray by this error message. In this case, since it is within this class that fuc is being defined, it wouldn't really make sense to implement it in this class. What the error is trying to tell you is that a non-abstract class cannot have abstract methods. As soon as you put an abstract method in the definition of a class, you must also mark the class itself as abstract.
Abstract keywords are used to label classes or methods as patterns. It's similar to interfaces but can contain variables and implementations of methods.
There are a lot of misunderstandings concerning abstract classes. Here is an example of an abstract Dog class. If a developer wants to create some basic Dog class for other developers or for himself to extend he declares the class as abstract. You can't instantiate the Dog class directly (nobody can), but you can extend Dog by your own class. SmartDog extends Dog etc.
All methods that are declared to be abstract by the Dog class must be implemented manually in each class that extends Dog.
For example, the abstract class Dog has an abstract method Dog::Bark(). But all Dogs bark differently. So in each Dog-subclasses you must describe HOW that dog barks concretely, so you must define eg SmartDog::Bark().
It means that the proper of an abstract class is having at least one abstract method. So your class has either to implement the method (non abstract), or to be declared abstract.
I wanted to use an abstract method within a non-abstract class (normal class?) and found that I could wrap the method's contents in an 'if' statement with get_parent_class() like so:
if (get_parent_class($this) !== false) {
Or, in action (tested in a file on cmd line: php -f "abstract_method_normal_class_test.php"):
<?php
class dad {
function dad() {
if (get_parent_class($this) !== false) {
// implements some logic
echo "I'm " , get_class($this) , "\n";
} else {
echo "I'm " , get_class($this) , "\n";
}
}
}
class child extends dad {
function child() {
parent::dad();
}
}
$foo = new dad();
$bar = new child();
?>
Output:
I'm dad
I'm child
PHP get_parent_class() Documentation

Categories