Thursday 28 March 2019

Abstract Class & Method

Abstract Class

  • An abstract class must be declared with an abstract keyword.
  • It can have abstract and non-abstract methods.
  • It cannot be instantiated.
  • It can have constructors and static methods also.
  • It can have final methods which will force the subclass not to change the body of the method.
Abstract classes 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 sub-classes 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());

Reference: https://stackoverflow.com/questions/2558559/what-is-abstract-class-in-php

Points on abstract class.
1. Declare classes and methods as abstract?
To declare a class as abstract, prefix the name of the class with the abstract keyword.

Example: abstract class Car { }

Declare abstract method with "abstract" keyword within the abstract class. Abstract method don't have body, only name and parameters inside parentheses.

Example: Create a public abstract method "calcNumMilesOnFullTank()". This method is skeleton for methods we will create in the child classes. These methods will return the number of miles a car can be driven on a tank of gas.

// Abstract classes are declared with the abstract keyword, and contain abstract methods.
abstract class Car {
  abstract public function calcNumMilesOnFullTank();
}

If an abstract method is created in the class, the class must be abstract.

2. Can an abstract class have non abstract methods?
An abstract class can have non abstract methods. In fact, it can even have properties, and properties couldn't be abstract.

Example: Add a protected property $tankVolume and public method setTankVolume().

abstract class Car {
  // Abstract classes can have properties
  protected $tankVolume;
  // Abstract classes can have non abstract methods
  public function setTankVolume($volume) {
    $this -> tankVolume = $volume;
  }
  // Abstract method
  abstract public function calcNumMilesOnFullTank();
}

3. Create child classes from an abstract class?
Objects cannot created from abstract classes. Create child classes that inherit the abstract class code. Child class will inherit the abstract class with the help of "extends" keyword.

The child classes that inherit from abstract classes must add bodies to the abstract methods.
Example: Create a child class "Honda", define abstract method in it which is inherited from the parent, calcNumMilesOnFullTank().

class Honda extends Car {
  // Since we inherited abstract method, we need to define it in the child class, 
  // by adding code to the method's body.
  public function calcNumMilesOnFullTank()
  {
    $miles = $this -> tankVolume*30;
    return $miles;
  }
}

We can create another child class from the Car abstract class and call it Toyota, and here again define the abstract method calcNumMilesOnFullTank() with a slight change in the calculation. We will also add to the child class its own method with the name of getColor() that returns the string "beige".

class Toyota extends Car {
  // Since we inherited abstract method, we need to define it in the child class, 
  // by adding code to the method's body.
  public function calcNumMilesOnFullTank() {
    return $miles = $this -> tankVolume*33;
  }

  public function getColor() {
    return "beige";
  }
}

Example: create a new object, $toyota1, with volume of 10 Gallons, and let it return the number of miles on full tank and the car's color.

$toyota1 = new Toyota();
$toyota1 -> setTankVolume(10);
echo $toyota1 -> calcNumMilesOnFullTank();//330
echo $toyota1 -> getColor();//beige

Access Modifiers in PHP

Access modifiers: 

These are used to set access rights with classes and their members(methods or properties) defined within the class.

Possible Access Modifiers

Private methods or properties can only be used from inside the class. This protects members from outside class access.

Public methods or properties can be accessed from both the inside and outside of the class.

Protected modifier: which allows code usage from both inside the class and from its child classes.

Abstract: This is used only for PHP classes and its methods. An abstract class can contain abstract methods. Non abstract class can not contain abstract methods.

Final: It prevents subclasses to override parent class members with final keyword.

The public access modifier

<?php
class Car {

  // public methods and properties.
  public $model;    

  public function getModel() {
    return "The car model is " . $this -> model;
  }
}

$ferrari = new Car();
//Here we access a property from outside the class
$ferrari -> model = "Ferrari";
//Here we access a method from outside the class
echo $ferrari -> getModel();

Result: The car model is Ferrari

The private access modifier

Example, $model is private property. While trying to set its value from outside the class, we encounter a fatal error.

<?php

class Car {

  //private property
  private $model;
    
  public function getModel() {
    return "The car model is " . $this -> model;
  }
}

$ferrari = new Car();

// We try to access a private property from outside the class.
$ferrari -> model = "Ferrari";
echo $ferrari -> getModel();

Result: Fatal error: Cannot access private property Car::$model

Access a private property?

As we cannot access private properties from outside the class but still we have to set & get the properties's values.

To interact with private properties, use public methods because public methods can only interact with both the code outside as well as inside the class. These public methods are of two kinds:
Setters: This sets the value of private properties.
Getters: This gets the value of the private properties.

Example: In this example, $carModel is private property. With the use of setter and getter methods, set and get value of private property.
To set car model value use setModel() and for get car model value use getModel() method.

<?php

class Car {

  //the private access modifier denies access to the method from outside the class’s scope
  private $model;

  //the public access modifier allows the access to the method from outside the class
  public function setModel($model) {
    $this -> model = $model;
  }
  
  public function getModel() {
    return "The car model is  " . $this -> model;
  }
}

$ferrari = new Car();
//Sets the car’s model
$ferrari -> setModel("Ferrari");
//Gets the car’s model
echo $ferrari -> getModel();

Result: The car model is Ferrari

Why we need access modifiers?

To limit the modifications to class's methods and properties done by the code outside of the class.
When we define any method or property as private, only methods within the class can use these private methods or properties. So to interact with private methods and properties, we need to create public methods. Inside these public methods, put your logic to validate and restrict data that comes from outside of the class.

In our example, we can validate that only certain car models can make their way, and be assigned to the private $model property, by defining the allowed alternatives for models in the public setModel() method. For this purpose, we define inside the setModel() method an array of allowed car models, and check that only these models are assigned to the $model property.

<?php
class Car {

  //the private access modifier denies access to the property from outside the class’s scope
  private $model;

  //the public access modifier allows the access to the method from outside the class
  public function setModel($model) {
    //validate that only certain car models are assigned to the $carModel property
    $allowedModels = array("Mercedes benz","BMW", "Ferrari");

    if(in_array($model,$allowedModels)) {
      $this -> model = $model;
    }
    else {
      $this -> model = "not in our list of models.";
    }
  }
  
  public function getModel() {
    return "The car model is  " . $this -> model;
  }
}


$ferrari = new Car();
//Sets the car’s model
$ferrari -> setModel("Ferrari");
//Gets the car’s model
echo $ferrari -> getModel();



Wednesday 27 March 2019

Inheritance in PHP


When a programmer writes same code more than once, code duplication problem occurs. Inheritance provides the ability to reduce code duplication in programming.
In inheritance, there is a parent class having its own methods and properties and child class/classes use the code from the parent.
Inheritance make us capable of reuse a piece of code (written only once in parent class) again & again in child class as we need.

Inherit code of another class by a class.

Inheritance provides the capability of reuse the code (written only once in parent class) in both the parent and child classs.
"extends": This keyword declares that one class inherits code from another class. Example:

class Parent {
  // The parent’s class code
}

class Child extends Parent {
  // The  child can use the parent's class code
}

Child class inherits the parent class so child class can use all the non-private methods and properties of parent class. We write code only once in parent and can use this code in both the parent and child classes.
ExampleI am having a parent class "car" and child class "sportsCar". Child class "sportsCar" is inheriting parent class "car" so class sportsCar having access to all of the car's class non-private methods and properties.
We have written setModel() and hello() public methods only once in the parent class. Class sportsCar and car can both use these methods.


//The parent class
class Car {
  // Private property inside the class
  private $model;

  //Public setter method
  public function setModel($model) {
    $this -> model = $model;
  }

  public function hello() {
    return "Hey! I am a <i>" . $this -> model . "</i><br />";
  }
}

//The child class inherits the code from the parent class
class SportsCar extends Car {
  //No code in the child class
}


//Create an instance from the child class
$sportsCar1 = new SportsCar();
 
// Set the value of the class’ property.
// For this aim, we use a method that we created in the parent
$sportsCar1 -> setModel('Ferrari');
 
//Use another method that the child class inherited from the parent class
echo $sportsCar1 -> hello();


Result: Hey! I am a Ferrari


Can a child class have its own methods and properties?


In inheritance, Child class can use all non-private methods and properties of parent class. But child class can have its own methods and properties as well. Child class can use the code inherited from parent class but parent class cannot use the child's class code.
Example: I am adding a property $style and a method driveItWithStyle() in child class as below: 

// The parent class has its properties and methods
class Car {
  
  //A private property or method can be used only by the parent.
  private $model;
  
  // Public methods and properties can be used by both the parent and the child classes.
  public function setModel($model) {
    $this -> model = $model;
  }
   
  public function getModel() {
    return $this -> model;
  }
}

//The child class can use the code it inherited from the parent class, and it can also have its own code 
class SportsCar extends Car{

  private $style = 'fast and furious';

  public function driveItWithStyle() {
    return 'Drive a '  . $this -> getModel() . ' <i>' . $this -> style . '</i>';
  }
}

//create an instance from the child class
$sportsCar1 = new SportsCar();
   
// Use a method that the child class inherited from the parent class
$sportsCar1 -> setModel('Ferrari');
  
// Use a method that was added to the child class
echo $sportsCar1 -> driveItWithStyle();
Result: Drive a Ferrari fast and furious.

The protected access control modifier

When a method or a property declared as protected, Both the parent and child class can use this method or property.
  • Private methods or properties can only be used from inside the class.
  • Public methods or properties can be accessed from both the inside and outside of the class.
  • Protected modifier: which allows code usage from both inside the class and from its child classes.
Example 1: What happen when we declare $model property as private in parent and still try to access it from its child class.

Try to call a private method or property from the outside of the class as done in code below:
Here is the code:

// The parent class
class Car {
  //The $model property is private, thus it can be accessed only from inside the class
  private $model;
  
  //Public setter method
  public function setModel($model) {
    $this -> model = $model;
  }
}
   
// The child class
class SportsCar extends Car{
  //Tries to get a private property that belongs to the parent
  public function hello() {
    return "Hey! I am a <i>" . $this -> model . "</i><br />";
  }
}
   
//Create an instance from the child class
$sportsCar1 = new SportsCar();
  
//Set the class model name
$sportsCar1 -> setModel('Ferrari');
   
//Get the class model name
echo $sportsCar1 -> hello();
Result:  Notice: Undefined property: SportsCar::$model

In above example, we get an error because hello() method (in child class) trying to use $model private property of parent class.

Now to fix above error, we can declare $model property as protected instead of private. Because when we declare a method or property as protected, this method or property can be used in both the parent and child classes..

// The parent class
class Car {
  //The $model property is now protected, so it can be accessed 
  // from within the class and its child classes
  protected $model;
   
  //Public setter method
  public function setModel($model) {
    $this -> model = $model;
  }
}
  
// The child class
class SportsCar extends Car {
  //Has no problem to get a protected property that belongs to the parent
  public function hello() {
    return "Hey! I am a <i>" . $this -> model . "</i><br />";
  }
}
  
//Create an instance from the child class
$sportsCar1 = new SportsCar();
  
//Set the class model name
$sportsCar1 -> setModel('Ferrari');
  
//Get the class model name
echo $sportsCar1 -> hello();

Result: Hey! I am a Ferrari.

Now it works, because we can access a protected code that belongs to a parent from a child class.

Override parent’s methods and properties in the child class?

Child class can have its own methods and properties. Child class can also override the methods and properties of the parent class as well.
To override class methods and properties, rewrite that method or property in child class which already exists in the parent class but write different code in method or assign different value to properties.
Example: created hello() method in the parent class that is returning string "Hey". Now after override this hello() method in child class, it is returning a different string "Hello". To override this hello() method name must be same as of parent class method name.

Here is the code:

// The parent class has hello method that returns "Hey".
class Car {
  public function hello() {
    return "Hey";
  }
}

//The child class has hello method that returns "Hello"
class SportsCar extends Car {
  public function hello() {
    return "Hello";
  }
}
    
//Create a new object
$sportsCar1 = new SportsCar();
  
//Get the result of the hello method
echo $sportsCar1 -> hello();

Result: Hello

The result reflects the fact that the hello() method from the parent class was overridden by the child method with the same name.

Prevent overriding the parent' methods by child class

To prevent overriding method of parent class in the child class, use "final" keyword. prefix "final" keyword in the parent method.

Example: I have declared hello() method as final in parent class and still try to override it in the child class. What will happen?
Or what will happen when we try to override a final method?

// The parent class has hello method that returns "Hey".

class Car {
  final public function hello() {
    return "Hey";
  }
}

//The child class has hello method that tries to override the hello method in the parent
class SportsCar extends Car {
  public function hello() {
    return "Hello";
  }
}

//Create a new object
$sportsCar1 = new SportsCar();
  
//Get the result of the hello method
echo $sportsCar1 -> hello();
Result: Fatal error: Cannot override final method Car::hello()

Since we declared the hello method as final in the parent, we cannot override the method in the child class.