In PHP, what do you mean by function overloading and function overriding. and what is the difference between both of them? couldn't figure out what is the difference between them.
Overloading is defining functions that have similar signatures, yet have different parameters. Overriding is only pertinent to derived classes, where the parent class has defined a method and the derived class wishes to override that method.
In PHP, you can only overload methods using the magic method __call.
An example of overriding:
<?php
class Foo {
function myFoo() {
return "Foo";
}
}
class Bar extends Foo {
function myFoo() {
return "Bar";
}
}
$foo = new Foo;
$bar = new Bar;
echo($foo->myFoo()); //"Foo"
echo($bar->myFoo()); //"Bar"
?>
Function overloading is not supported by PHP. It occurs when you define the same function name twice (or more) using different set of parameters. For example:
class Addition {
function compute($first, $second) {
return $first+$second;
}
function compute($first, $second, $third) {
return $first+$second+$third;
}
}
In the example above, the function compute is overloaded with two different parameter signatures. *This is not yet supported in PHP. An alternative is to use optional arguments:
class Addition {
function compute($first, $second, $third = 0) {
return $first+$second+$third;
}
}
Function overriding occurs when you extend a class and rewrite a function which existed in the parent class:
class Substraction extends Addition {
function compute($first, $second, $third = 0) {
return $first-$second-$third;
}
}
For example, compute overrides the behavior set forth in Addition.
Strictly speaking, there's no difference, since you cannot do either :)
Function overriding could have been done with a PHP extension like APD, but it's deprecated and afaik last version was unusable.
Function overloading in PHP cannot be done due to dynamic typing, ie, in PHP you don't "define" variables to be a particular type. Example:
$a=1;
$a='1';
$a=true;
$a=doSomething();
Each variable is of a different type, yet you can know the type before execution (see the 4th one).
As a comparison, other languages use:
int a=1;
String s="1";
bool a=true;
something a=doSomething();
In the last example, you must forcefully set the variable's type (as an example, I used data type "something").
Another "issue" why function overloading is not possible in PHP:
PHP has a function called func_get_args(), which returns an array of current arguments, now consider the following code:
function hello($a){
print_r(func_get_args());
}
function hello($a,$a){
print_r(func_get_args());
}
hello('a');
hello('a','b');
Considering both functions accept any amount of arguments, which one should the compiler choose?
Finally, I'd like to point out why the above replies are partially wrong;
function overloading/overriding is NOT equal to method overloading/overriding.
Where a method is like a function but specific to a class, in which case, PHP does allow overriding in classes, but again no overloading, due to language semantics.
To conclude, languages like Javascript allow overriding (but again, no overloading), however they may also show the difference between overriding a user function and a method:
/// Function Overriding ///
function a(){
alert('a');
}
a=function(){
alert('b');
}
a(); // shows popup with 'b'
/// Method Overriding ///
var a={
"a":function(){
alert('a');
}
}
a.a=function(){
alert('b');
}
a.a(); // shows popup with 'b'
Overloading Example
class overload {
public $name;
public function __construct($agr) {
$this->name = $agr;
}
public function __call($methodname, $agrument) {
if($methodname == 'sum2') {
if(count($agrument) == 2) {
$this->sum($agrument[0], $agrument[1]);
}
if(count($agrument) == 3) {
echo $this->sum1($agrument[0], $agrument[1], $agrument[2]);
}
}
}
public function sum($a, $b) {
return $a + $b;
}
public function sum1($a,$b,$c) {
return $a + $b + $c;
}
}
$object = new overload('Sum');
echo $object->sum2(1,2,3);
Although overloading paradigm is not fully supported by PHP the same (or very similar) effect can be achieved with default parameter(s) (as somebody mentioned before).
If you define your function like this:
function f($p=0)
{
if($p)
{
//implement functionality #1 here
}
else
{
//implement functionality #2 here
}
}
When you call this function like:
f();
you'll get one functionality (#1), but if you call it with parameter like:
f(1);
you'll get another functionality (#2). That's the effect of overloading - different functionality depending on function's input parameter(s).
I know, somebody will ask now what functionality one will get if he/she calls this function as f(0).
Method overloading occurs when two or more methods with same method name but different number of parameters in single class.
PHP does not support method overloading.
Method overriding means two methods with same method name and same number of parameters in two different classes means parent class and child class.
I would like to point out over here that Overloading in PHP has a completely different meaning as compared to other programming languages. A lot of people have said that overloading isnt supported in PHP and by the conventional definition of overloading, yes that functionality isnt explicitly available.
However, the correct definition of overloading in PHP is completely different.
In PHP overloading refers to dynamically creating properties and methods using magic methods like __set() and __get(). These overloading methods are invoked when interacting with methods or properties that are not accessible or not declared.
Here is a link from the PHP manual : http://www.php.net/manual/en/language.oop5.overloading.php
Overloading: In Real world, overloading means assigning some extra stuff to someone. As as in real world Overloading in PHP means calling extra functions. In other way You can say it have slimier function with different parameter.In PHP you can use overloading with magic functions e.g. __get, __set, __call etc.
Example of Overloading:
class Shape {
const Pi = 3.142 ; // constant value
function __call($functionname, $argument){
if($functionname == 'area')
switch(count($argument)){
case 0 : return 0 ;
case 1 : return self::Pi * $argument[0] ; // 3.14 * 5
case 2 : return $argument[0] * $argument[1]; // 5 * 10
}
}
}
$circle = new Shape();`enter code here`
echo "Area of circle:".$circle->area()."</br>"; // display the area of circle Output 0
echo "Area of circle:".$circle->area(5)."</br>"; // display the area of circle
$rect = new Shape();
echo "Area of rectangle:".$rect->area(5,10); // display area of rectangle
Overriding : In object oriented programming overriding is to replace parent method in child class.In overriding you can re-declare parent class method in child class. So, basically the purpose of overriding is to change the behavior of your parent class method.
Example of overriding :
class parent_class
{
public function text() //text() is a parent class method
{
echo "Hello!! everyone I am parent class text method"."</br>";
}
public function test()
{
echo "Hello!! I am second method of parent class"."</br>";
}
}
class child extends parent_class
{
public function text() // Text() parent class method which is override by child
class
{
echo "Hello!! Everyone i am child class";
}
}
$obj= new parent_class();
$obj->text(); // display the parent class method echo
$obj= new parent_class();
$obj->test();
$obj= new child();
$obj->text(); // display the child class method echo
There are some differences between Function overloading & overriding though both contains the same function name.In overloading ,between the same name functions contain different type of argument or return type;Such as:
"function add (int a,int b)" & "function add(float a,float b);
Here the add() function is overloaded.
In the case of overriding both the argument and function name are same.It generally found in inheritance or in traits.We have to follow some tactics to introduce, what function will execute now.
So In overriding the programmer follows some tactics to execute the desired function where in the overloading the program can automatically identify the desired function...Thanks!
Overloading: Declaring a function multiple times with a different set of parameters like this:
<?php
function foo($a) {
return $a;
}
function foo($a, $b) {
return $a + $b;
}
echo foo(5); // Prints "5"
echo foo(5, 2); // Prints "7"
?>
Overriding: Replacing the parent class's method(s) with a new method by redeclaring it like this:
<?php
class foo {
function new($args) {
// Do something.
}
}
class bar extends foo {
function new($args) {
// Do something different.
}
}
?>
PHP 5.x.x does not support overloading this is why PHP is not fully OOP.
Related
I have two classes A and B, where B extends A and adds some methods. I have a class C with a method that accepts A as parameter for generalization purposes. The issue is that once inside the method, I want to access the methods of class B on the object, but I'm not able to do so. Don't get error, but have null in the return, when I have dumped the object and know that it holds data.
Sorry if it's seems ridiculous, but I'm trying to use a bahaviour that you would expect in normal inheritance. Maybe be I'm missing something and it is my fault, but have no idea of what is happening here.
Please, if you have any idea of how to do this, help me.
Some code:
public function createProject(AssociatedProjectInterface $project_data){
if(!is_a($project_data, 'class\path\GithubProject')){
throw new InvalidArgumentException('The argument needs to be of type: GithubProject.');
}
$repo = $this->client->api('repo')->create(
$project_data->getTitle(),
$project_data->getDescription(),
null,
!$project_data->getIsPrivate(),
null,
$project_data->getIssuesEnabled(),
$project_data->getWikiEnabled());
}
Thanks.
Note that PHP's type checking is very loose. It calls the method of the class that is passed. The type checking is only taking place at the moment that function is called. So in the example below, testType must be past an object of type A or a descendant of A. After that initial check, no type checking is done at all! So the function can call any method declared in A or B. If a method is declared in both, it is considered overridden and the version in B is used.
<?php
class A {
function foo() {
echo 'A:foo';
}
}
class B extends A {
function foo() {
echo 'B:foo';
}
function bar() {
echo 'B:bar';
}
}
function testType(A $a)
{
$a->foo(); // B:foo
$a->bar(); // B:bar <- This will succeed even though there's no bar() in A.
}
$a = new B();
testType($a);
What you're asking for is NOT expected in normal object-oriented inheritance, but apparently works in PHP. Normally, if a method expects an object of class A, you can pass an object of class B that extends A, but the method will treat the object as though it were of class A. This means that when you call methods inherent to B, you are calling methods that don't exist and an error should be thrown.
In php though, momma don't care. As proof run the following minimal test:
<?php
class A {
public function foo() {
echo "in foo\n";
}
}
class B extends A {
public function bar() {
echo "in bar\n";
}
}
class C {
public function test(A $b) {
$b->foo();//works, because foo exists in the A class definition
$b->bar();//also works for B, but not A
}
}
$a = new A();
$b = new B();
$c = new C();
$c->test($b);
$c->test($a);//Will throw an error because the method bar() is not found
Note that it is considered extremely bad programming practice to ask for A when the code will quite literally die if it requires B. You should really avoid this situation.
I was looking to some php codes, and I saw an object that will call multiple methods in the same line.
I've tried to understand how to do it, and why we need to use it?
$object->foo("Text")->anotherFoo()->bar("Aloha")
What this styling called? and what is the best way to use it in php applications.
This syntax is called method chaining, and it's possible because each method returns the object itself ($this). This is not necessarily always the case, it's also used to retrieve an object's property that in turn also can be an object (which can have properties that are objects, and so on).
It is used to reduce the amount of lines that you need to write code on. Compare these two snippets:
Without chaining
$object->foo("Text");
$object->anotherFoo();
$object->->bar("Aloha");
Using method chaining
$object->foo("Text")->anotherFoo()->bar("Aloha");
this is used when the first function returns an object that will contains the second function that will return another object and so on...
class X
{
public function A()
{
echo "A";
}
public function B()
{
echo "B";
}
}
class Y
{
public function A()
{
echo "Y";
}
public function B()
{
return $this;
}
}
$y = new Y();
$y->B()->A();//this will run
$x = new X();
$x->A()->B();//this won't run, it will output "A" but then A->B(); is not valid
I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}
I'd like to do something like this:
public static function createDynamic(){
$mydynamicvar = 'module';
self::$mydynamicvar = $value;
}
and be able to access the property from within the class with
$value = self::$module;
I don't know exactly why you would want to do this, but this works. You have to access the dynamic 'variables' like a function because there is no __getStatic() magic method in PHP yet.
class myclass{
static $myvariablearray = array();
public static function createDynamic($variable, $value){
self::$myvariablearray[$variable] = $value;
}
public static function __callstatic($name, $arguments){
return self::$myvariablearray[$name];
}
}
myclass::createDynamic('module', 'test');
echo myclass::module();
static variables must be part of the class definition, so you can't create them dynamically. Not even with Reflection:
chuck at manchuck dot com 2 years ago
It is important to note that calling ReflectionClass::setStaticPropertyValue will not allow you to add new static properties to a class.
But this looks very much like a XY Problem. You probably don't really want to add static properties to a PHP class at runtime; you have some use case that could be fulfilled also that way. Or that way would be the fastest way, were it available, to fulfill some use case. There well might be other ways.
Actually the use cases below are yet again possible solutions to some higher level problem. It might be worth it to reexamine the high level problem and refactor/rethink it in different terms, maybe skipping the need of meddling with static properties altogether.
I want a dictionary of properties inside my class.
trait HasDictionary {
private static $keyValueDictionary = [ ];
public static function propget($name) {
if (!array_key_exists($name, static::$keyValueDictionary) {
return null;
}
return static::$keyValueDictionary[$name];
}
public static function propset($name, $value) {
if (array_key_exists($name, static::$keyValueDictionary) {
$prev = static::$keyValueDictionary[$name];
} else {
$prev = null;
}
static::$keyValueDictionary[$name] = $value;
return $prev;
}
}
class MyClass
{
use Traits\HasDictionary;
...$a = self::propget('something');
self::propset('something', 'some value');
}
I want to associate some values to a class, or: I want a dictionary of properties inside some one else's class.
This actually happened to me and I found this question while investigating ways of doing it. I needed to see, in point B of my workflow, in which point ("A") a given class had been defined, and by what other part of code. In the end I stored that information into an array fed by my autoloader, and ended up being able to also store the debug_backtrace() at the moment of class first loading.
// Solution: store values somewhere else that you control.
class ClassPropertySingletonMap {
use Traits\HasDictionary; // same as before
public static function setClassProp($className, $prop, $value) {
return self::propset("{$className}::{$prop}", $value);
}
public static function getClassProp($className, $prop) {
return self::propget("{$className}::{$prop}");
}
}
// Instead of
// $a = SomeClass::$someName;
// SomeClass::$someName = $b;
// we'll use
// $a = ClassPropertySingletonMap::getClassProp('SomeClass','someName');
// ClassPropertySingletonMap::setClassProp('SomeClass','someName', $b);
I want to change, not create, an existing property of a class.
// Use Reflection. The property is assumed private, for were it public
// you could do it as Class::$property = $whatever;
function setPrivateStaticProperty($class, $property, $value) {
$reflector = new \ReflectionClass($class);
$reflector->getProperty($property)->setAccessible(true);
$reflector->setStaticPropertyValue($property, $value);
$reflector->getProperty($property)->setAccessible(false);
}
Static properties must be defined in the class definition. Therefore, real static properties cannot be created dynamically like regular properties.
For example, if you run this:
<?php
class MyClass
{
public static function createDynamic()
{
$mydynamicvar = 'module';
self::$mydynamicvar = $value;
}
}
MyClass::createDynamic();
var_dump(MyClass::$mydynamicvar);
var_dump(MyClass::$module);
...you'll get this error
Fatal error: Access to undeclared static property: MyClass::$mydynamicvar test.php on line 8
Notice how the error occurs on line 8 when trying to set the property instead of line 14 or 15 (as you might expect if you were simply doing it wrong and dynamically creating static properties was actually possible).
A related problem that IS possible (in PHP 5.4.0 and up) is to include various separate groups of static variable or constant declarations and group them together into one class declaration.
Here is an example:
trait Added1 // This can be located in one Include file
{
static
$x="hello"; // Can declare more variables here
}
trait Added2 // This can be located in another Include file
{
static
$y="world"; // Can declare more variables here
}
class G // Global constant and variable declarations class
{
use Added1, Added2; // Combines all variable declarations
}
echo G::$x." ".G::$y; // Shows "hello world" on the web page
If I have a function:
function this($a){
return $a;
}
If I wanted to redefine the function, would it be as simple as rewriting it?
function this($a, $b){ //New this function
return $a * $b;
}
Nope, that throws an error:
Fatal error: Cannot redeclare foo()
The runkit provides options, including runkit_function_rename() and runkit_function_redefine().
If you mean overloading in a Java sense, then the answer is no, this is not possible.
Quoting the PHP manual on functions:
PHP does not support function overloading, nor is it possible to undefine or redefine previously-declared functions.
You could use the runkit extension but usage of runkit in production scenarios is generally considered doubtful practice. If you want to exchange algorithms at runtime, have a look at the Strategy pattern or Anonymous functions instead.
If by redefine you mean add to an existing userland function, refactor, substitute or rewrite, then yes: it is as simple as you've shown. Just add the additional code to the function, but make sure you set a default for backwards compatibility.
Another option would be to use http://antecedent.github.io/patchwork
Patchwork is a PHP library that makes it possible to redefine user-defined functions and methods at runtime, loosely replicating the functionality runkit_function_redefine in pure PHP 5.3 code, which, among other things, enables you to replace static and private methods with test doubles.
You can't redefine or 'undefine' a function in PHP (without resorting to third-party modules). However, you can define a function conditionally.
So, if you know function A can be defined elsewhere, but not always, you can wrap it like this:
if (!function_exists('A')) {
function A() {
// default A implementation
}
}
Then you only need to make sure the implementation you want is encountered first:
function A() {
// another A implementation
}
I've got a library of functions that sometimes I just don't want invoked while I'm testing (typically database updates). If I have, for example, a few different db update functions that are all over the code. instead of commenting out the code, I just create a special class (e.g. class foo {}). Define a global variable (e.g., $DEBUG) and a dummy function (e.g., function dummy {}).
Inside foo define all the (public static) functions you need to mimic as
$fn = isset($DEBUG) ? 'dummy' : 'real function';
return call_user_func_array($fn,func_get_args());
Plus you have the advantages of now doing other things, like logging the calls and parameters.
Then simply replace all your calls to real_function(...) with foo::real_function(...). Usually just a simple search/replace (or leave it there; depending on what's going on in the function and how often it's getting called the overhead may be irrelevant).
I have good news and bad news.
The good news
It is possible (link(s) below).
The nadnews
There are 2 bad news:
By default, only userspace functions may be removed, renamed, or modified. In order to override internal functions, you must enable the runkit.internal_override setting in php.ini.
And the second bad news: You havbe to sacrifice code readability.
Example:
<?php
function this($a){
return $a;
}
echo this(0);
$f_name = 'this';
$f_args = '$a';
$f_code = 'return $a*$b;';
runkit_function_redefine($f_name, f_args, f_code);
echo this(1,3);
Oh, and one more thing, using this as a name for a function may create confusion, due to the methods of a object of a class being able to use this.something to reffer to the variable something that is in the method and have the same name as the variable something from the object itself. Here is an example
<?php
class theclass{
$a = 'a';
function a($a){
echo $a;
$a = this.$a;
}
}
theclass $object = new theclass();
$object -> a('b'); // will echo: ab
You cannot redeclare functions, without runtime hacking, but in various situations you may, in fact, redefine them.
Namely, if they are stored in a variable. Though, under the hood this is really reassigning the symbol to a new function.
$action['doSomething'] = function($arguments){
return 'false';
};
$action['doSomething'] = function($arguments){
return var_export($arguments,true);
};
echo $action['doSomething']('Hello world');
There is also the case of inheritance.
namespace CoolCorp\AwesomeGame;
class World{
const TILE_SIZE = 8; // size in pixels of an N x N square
const GAME_TICK = 25; // milliseconds between action sequence frames
const UP = 1;
const DOWN = 2;
const LEFT = 3;
const RIGHT = 4;
.
.
}
class Character2D{
const WALK = 1;
const RUN = 2;
public $mode=1;
public $x=0;
public $y=0;
public $next_x=0;
public $next_y=0;
.
.
public function move($direction){
$selected_mode = self::$mode == self::RUN ?
__NAMESPACE__ . '\RunMode'
: __NAMESPACE__ . '\WalkMode';
class_alias($selected_mode, 'game_movement');
switch($direction){
case UP: game_movement::up($this); break;
case DOWN: game_movement::down($this); break;
case LEFT: game_movement::left($this); break;
case RIGHT: game_movement::right($this); break;
}
$this->AnimateNextPositionAsync(WORLD::GAME_TICK);
}
public function move_Alternative($direction){
$game_movement = self::$mode == self::RUN ?
__NAMESPACE__ . '\RunMode'
: __NAMESPACE__ . '\WalkMode';
switch($direction){
case UP: $game_movement::up($this); break;
case DOWN: $game_movement::down($this); break;
case LEFT: $game_movement::left($this); break;
case RIGHT: $game_movement::right($this); break;
}
$this->AnimateNextPositionAsync(WORLD::GAME_TICK);
}
.
.
}
class WalkMode{
public static function up($actor){
$actor->next_y -= World::TILE_SIZE;
};
public static function down($actor){
$actor->next_y += World::TILE_SIZE;
};
public static function left($actor){
$actor->next_x -= World::TILE_SIZE;
};
public static function right($actor){
$actor->next_x += World::TILE_SIZE;
};
}
class RunMode extends WalkMode{
public static function up($actor){
$actor->next_y -= World::TILE_SIZE*2;
};
public static function down($actor){
$actor->next_y += World::TILE_SIZE*2;
};
public static function left($actor){
$actor->next_x -= World::TILE_SIZE*2;
};
public static function right($actor){
$actor->next_x += World::TILE_SIZE*2;
};
}
A bit contrived but illustrative of how you may redefine a function in a child class and use to achieve a goal. The second example assumes you are not using an ancient PHP version.
You can't have both functions declared at the same time, that will give an error.
You can't redeclare it. If your question is just about overloading that example, how about:
function this($a, $b=1)
{
return $a * $b;
}
Setting an appropriate default to any new arguments that you add might help for backwards compatibility, i.e.:
function this($a, $b=1){ //New this function with a sane default.
return $a * $b;
}
I also recommend, for clarity, generally avoiding using this for function/variable names.