Open In App

Covariance and Contravariance in PHP

Improve
Improve
Like Article
Like
Save
Share
Report

Covariance: In PHP, the return type of method which belongs to the child can be more specific compared to the return type of method of parent. This is done through covariance. For example, consider the parent class “Bank”, and “SB” and “BOI” to be its children.




<?php
  
// Parent class declared
abstract class bank {
    protected  $name;
   
    public function __construct( $name) {
        $this->name = $name;
    }
   
    abstract public function account();
}
  
// Child 1
class SBI extends bank {
    public function account() {
        echo $this->name . " has an SBI account";
    }
}
  
// Chil2
class BOI extends bank {
    public function account() {
        echo $this->name . " has a BOI account";
    }
}
  
interface acc_open {
    public function open($name): bank;
}
   
class SBI_acc_open implements acc_open {
      
    // Not returning the parent class 
    // type but the child's return 
    // type instead 
    public function open($name): SBI {
        return new SBI($name);
    }
}
   
class BOI_acc_open implements acc_open {
      
    // Not returning the parent class
    // type but the child's return
    // type instead
    public function open( $name) : BOI {
        return new BOI($name);
    }
}
   
$a = (new SBI_acc_open)->open("Arshit");
$a->account();
echo "\n";
   
$b = (new BOI_acc_open)->open("Simon");
$b->account();
?>


Output:

Arshit has an SBI account
Simon has a BOI account

Contravariance: In PHP, the parameters of the method which belong to the child can be less specific compared to the parameters of the method of parent. This is done through contravariance.




<?php
  
// Parent class declared
abstract class bank {
    protected  $name;
    
    public function __construct( $name) {
        $this->name = $name;
    }
    
    public function acc_no(account_no $n) {
        echo $this->name . " has " . get_class($n);
    }
}
  
// Child 1
class SBI extends bank {
    public function account() {
        echo $this->name . " has an SBI account ";
    }
      
    // The function acc_no is overridden in 
    // the class SBI that allows any 
    // account_detail type object, it will 
    // show contravariance behavior
    public function acc_no(account_detail $n) {
        echo $this->name . " has an SBI "
                . get_class($n);
    }
}
  
// Child2
class BOI extends bank {
    public function account() {
        echo $this->name . " has a BOI account";
    }
}
  
interface acc_open {
    public function open($name): bank;
}
    
class SBI_acc_open implements acc_open {
      
    // Not returning the parent class type
    // but the child's return type instead
    public function open($name): SBI {
        return new SBI($name);
    }
}
    
class BOI_acc_open implements acc_open {
      
    // Not returning the parent class type 
    // but the child's return type instead
    public function open( $name) : BOI {
        return new BOI($name);
    }
}
   
class account_detail{} 
class account_no extends account_detail{}
   
$k = (new BOI_acc_open)->open("Shreyank");
$c = new account_no();
$k->acc_no($c);
echo("\n");
   
$y = (new SBI_acc_open)->open("Shrey");
$d = new account_detail();
$y->acc_no($d);
?>


Output:

Shreyank has account_no
Shrey has an SBI account_detail

Note: By excluding type limitings on parameters of the child method, partial contravariance was achieved in PHP version 7.2.0. and in PHP version 7.4.0, complete contravariance and covariance were achieved. All older versions before version 7.2.0 will show error.



Last Updated : 21 Aug, 2020
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads