Covariance and Contravariance in PHP
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.
Please Login to comment...