Method overloading in PHP is bad practice? - php

Trying to achieve method overloading using PHP (don't confuse with overloading definition from PHP manual), is not easy there is clear trade off, because of nature of PHP you have to have one method and if or switch statement inside to provide overloading, it creates procedural code that is difficult to read in long methods.
Is there any advantage of having method overloading in PHP, can it be achieved in any other way?
class MyClass {
public function doMany($input) {
if (is_array($input)) {
...
} else if (is_float($input)) {
...
}
}
}
versus traditional approach
class MyClass {
public function doArray(array $input) {
...
}
public function doFloat(float $input) {
...
}
}

The traditional approach would be:
class Aclass {
public function doStuff(int $a) {
// return other stuff
}
public function doStuff(float $a) {
// return other stuff
}
}
Notice the same function name just different type for the paramaters.
Your first approach is usually the way to go if you want to simulate overloading in php. Generally speaking you don't really need overloading in PHP since it's loosely type and by definition you can't really have overloading.
To answer your question. If you really need to have overloading, then your first approach seems appropriate. Use a switch to make it more readable.
Disclaimer: While you can do that, I don't recommend it. Heck, you can do just about anything if you want to. It doesn't mean you should.

Related

Any way to declare a regular function within a class as a method?

I have a scenario where I'm trying to incorporate several people's PHP work, some of it OOP and some not. I want to pull a library file of functions into a class and have those functions be available to other files that reference the class. I know I can just call the library functions directly, but then I would have to update all of the dependent files to do likewise. Example:
class do_something {
function test_state() {
...
}
if ($this->test_state($var)) {
...
}
}
Where test_state() is identical to the same-named function in the library file, making for redundant code to keep sync'd. That can be changed to:
class do_something {
if (test_state($var)) {
...
}
}
But that creates the aforementioned problem of $this->test_state() not being available to files dependent on the class. What I'd like to be able to do is something like:
class do_something {
public function test_state() = test_state();
if ($this->test_state($var)) {
...
}
}
Obviously, that's a very rough and incorrect example of what I'm trying to do... Is there any way in OOP to make that sort of reassignment, making the method of the same name as the function available within the class?
You can use a workaround to simulate this. In fact you would often want this approach to bolt on closures to objects in PHP. It leverages the magic __call method in PHP to redirect method calls to ordinary functions (beware: no $this available).
class do_something {
function __call($func, $args) {
if (isset($this->$func) && is_callable($this->$func)) {
return call_user_func_array($this->$func, $args);
}
}
}
Then you can "register" functions that you want to allow (or closures) with a simple assignment:
$do_something->function_name = "global_function_name";
$do_something->or_even = array("other_class", "method");
But again, this doesn't make them proper methods as such.
You'd create your base utility class, then extend it. See PHP's manual entry for inheritance for the details. I'm not saying this is the best solution for your exact situation, but I think it answers the question you were trying to get at.
What you're asking for isn't possible directly, but can be faked with a quick (horrible) hack:
class do_something {
public function test_state($param) {
return test_state($param);
}
...
$this->test_state($param);
...
}
Good luck with refactoring!

PHP: how to reuse code (oop)?

I have studied in php oop and stocked in the concept of reusable code.
I have seen an example like
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
And implement it:
// Implement the interface
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
I can understand the code but not sure why it is reusable. Every time I want to add a new function in iTemplate interface, my Template class needs to be changed too. I don't understand the concept of "reuse". I appreciate any help. Thanks.
Interfaces aren't directly for code reuse. They are for abstraction. They enable classes that use the template to check for the interface instead of the base template class. That way it separates implementation from the interface declaration.
So if your method does something with a template class, checking for an object of instance template would hard code a dependency on that class. But in reality you don't care what class you get, you just care if it adheres to the iTemplate interface (since that's all you're calling anyway).
public function foo(Template $template) {
vs:
public function foo(iTemplate $template) {
Now, as far as code re-use, interfaces aren't really designed for that. Inheritance typically is. Basically think of inheritance as extending an abstraction. Let me give you an example:
If you were to create a set of classes for birds, you could approach it with inheritance and without it. Let's see how we might do it without:
interface iBird {
public function fly();
public function speak();
public function swim();
public function walk();
}
class Duck implements iBird {
public function fly() {
//Fly here
}
public function speak() {
// Quack here
}
public function swim() {
//Swim here
}
public function walk() {
//Walk here
}
}
class Turkey implements iBird {
public function fly() {
//Fly here, but limited
}
public function speak() {
//Make turkey sound here
}
public function swim() {
throw new Exception('Turkeys can not swim!');
}
public function walk() {
//Walk here
}
}
Now, this is a simple example, but you can see that in those two birds, the walk() functions will likely be identical (and hence violate DRY)...
Let's see how that might look with a single tier inheritance:
abstract class Bird implements iBird {
public function fly() {
//Fly here
}
abstract public function speak();
public function swim() {
//Swim here
}
public function walk() {
//Walk here
}
}
class Duck extends Bird {
public function speak() {
//Quack here
}
}
class Turkey extends Bird {
public function speak() {
//Make turkey sound here
}
public function swim() {
throw new Exception('Turkeys can not swim!');
}
}
Now, you can see we just re-used 3 of the methods! We didn't declare speak(), since it will be always overriden (since no two birds sound alike).
Sounds good right? Well, depending on our needs, we may want to add other abstract types. So lets say we were making a lot of different types of birds... We would have some that didn't swim, so we might create an abstract class NonSwimmingBird that extends Bird, but throws the exception for us. Or a NonFlyingBird, or a ShortRangeBird...
Now, we're really on the track as far as code re-use, but we're hitting a wall in another area. Suppose we have a bird that doesn't fly or swim. What class do we inherit from? Either way, we're duplicating code. So we need to find another way out. Well, how do we do it? Through Design Patterns... Instead of direct inheritance, we could use a decorator pattern to add those traits on the fly. (There are other patterns that can be used here, the point is to show that inheritance alone won't suit all needs. And Patterns alone won't either. You need a good architecture using both worlds based upon what your exact needs are)...
The point is, it all depends on your needs. If you only have 2 "classes" of objects you're going to architect something much simpler than if you are planning on having thousands. The point of what I wrote here is to demonstrate how you can use straight inheritance to enforce some DRY principals (but also how straight inheritance can cause code duplication as well). The big thing, is don't try to stick to DRY just because you don't want to repeat yourself. Stick to DRY, but make sure that you're combining and extending where it's reasonable to, otherwise you're creating yourself a maintenance headache. Stick to the Single Responsibility Principal, and you should be fine...
Interface writes only 1 time in beginning of development. And only after this writes other classes implements of this Interface. Interface - is a fundament.
Note: method setVariable isn't required. There are good magic methods in PHP as __get(), and __set().
Interfaces are usually useful in cases where you want something to be interchangeable. Imagine you'd build a Plugin aware application. You then have the interface iPlugin:
interface iPlugin {
public function init();
/* .. */
}
and all Plugins would implement that interface. A plugin manager could then easily check if a Plugin implements the interface and call the init() method on it.
Code doesn't need to be OO to be reusable, although in many cases that helps.
Code certainly doesn't need to use interfaces to be reusable, although again in some cases that will help.
The key to writing reusable code is to write code that is clearly written, well-commented, uses consistent naming and calling conventions, and is more general than it strictly needs to be for the problem at hand.
One of the simplest and most powerful techniques for writing reusable code in PHP is writing methods that accept either a variable number of arguments, or accept an associative array of parameters.
Often, code that didn't start out "intending" to be reusable turns out to be something you'll want to reuse. Typically, code starts "inline" and then you discover you need to do exactly, or nearly exactly, the same thing in more than one place. When you find yourself copying and pasting code it's time to refactor it as a function.
Similarly, when you find yourself wishing a function you had defined in file X would be really helpful in file Y, it's time to move it into a module.
The best way to learn all this is by experience. Some people will tell you to architect this stuff from the beginning, and that's certainly a good idea if you have the insight and experience to do so, but it's just as valid to do so from the bottom up, and it's probably the best way to learn.
Reusability of Object oriented Programming is the use of previous class or function or method in the present class but no problem of previous class.

php OOP function declarations

I'm a big fan of OOP in php, but i feel like defining class methods gets disorganized so fast. I have a pretty good background in OOP in C++, and i am pretty comfortable with how it is handled there, and am curious if there are ways to do it similarly in php.
To be more specific, here is what i mean. I like how in C++ you can define a class header (myclass.h) and then define the actual details of the functions in the implementation file (myclass.cc). Ive found that this can easily be replicated using interfaces in php, but i havent found a good solution for the following:
I like to organize my code in C++ in different files based on how they are accessed, so for example, public methods that can be called outside of the class would be in 1 place, and private methods would be organized somewhere else - this is personal preference.
Ive tried to define class methods in php like:
private function MyPHPClass::myFunction(){ }
when the definition isnt directly inside the class block( { } ), but i havent had any success doing this.
Ive been through all of the pages on php.net, but couldnt find anything like this. Im assuming that there is no support for something like this, but thought i would ask anyway.
thanks
You can't do this. The class declarations are Java-like.
You have to put everything in one file or, at minimum, have some helper classes -- be they only static methods to which you forward or calls or with you deferring some implementation to encapsulated objects. You can also use the __call and __callstatic magic methods to reduce the size of your stubs, but that only works for public methods and I would recommend that you avoid magic methods.
EDI2: As RobertPitt pointed in a comment, you should consider alternative strategies that divide the functionality between several classes. It has the added advantage that it can make your code more decoupled. If you need, you can still unify the functionality of the several classes behind a façade.
EDIT: By using magic methods, I mean something like this:
class MyClassHelper {
public function method_one(array $args) {
...
}
public function method_two(array $args) {
...
}
}
class MyClass {
/**
* #var MyClassHelper
*/
private $helper;
private static $ALLOWED_METHODS = array("method_one" => NULL,
"method_two" => NULL);
public function __call($name, $arguments) {
$name = strtolower($name);
if (array_key_exists($name, self::$ALLOWED_METHODS) {
$helper->$name($arguments);
}
else
throw new Exception(...);
}
}
I should recommend that you avoid this, there are many pitfalls to this (handling of references, no code completion).
Im not really a C++ / C# Programmer but interfaces in php i can give you an exampe to see if this helps.
Interface
interface IDatabase
{
public function connect($dns = '');
public function disconnect($flushCache = false); //Do not use braces, Code free in interfaces
}
Database abstract base class
abstract class Database
{
//Some driver logic here to laod mysql,oracle etc
}
MySql Driver
class DBDriver_MySQl extends Database implements IDatabase
{
public function connect($dns = '')
{
//Connection logic.
}
public function disconnect($flushDns)
{
//Disconnect Login
}
}
Hope this is what your looking for.

Define two functions, or branch within one?

I was reading about how to detect the encoding of a file in PHP, and on some blog or somewhere, it was suggested to do this:
if (function_exists('mb_detect_encoding')) {
function is_utf8($str) {
// do stuff using the mb* libraries
}
} else {
function is_utf8($str) {
// do stuff manually
}
}
To me this feels very messy, and could be replaced with this:
function is_utf8($str) {
if (...) {
// mb stuff here
} else {
// manual stuff here
}
}
However, I can also see that it also has some benefits. Depending how complicated the if statement is, and how often the function is called, this might be much more efficient. My question is this: At what point would you consider splitting a function into two like in the first example? Are there any other pros/cons that I've missed?
Edit: Please don't get hung up on the example here, the question is about this practice in general.
My gut reaction is to go with a single declaration of the is_utf8 function. The PHP engine is mighty good at optimization and the overhead of multiple calls to function_exists() should be negligible.
A good practice, maybe not in that case, but in general might involve the use of OOP (objects) with factory methods.
class my_utf8
{
// A static method that determine what object to create
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
}
class my_utf8_with_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff using the mb* libraries
}
}
class my_utf8_without_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff without the mb* libraries
}
}
And in your application :
global $myUtfInstance;
// Call once
$myUtfInstance = my_utf8::factory();
// later and forever...
$myUtfInstance->is_utf8($str);
You could also involve a singleton pattern depending on what you do. It does not skip the IF but eliminate the need of a global variable.
class my_utf8
{
private static $instance;
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = self::factory();
}
return self::$instance;
}
}
And in your code :
my_utf8::getInstance()->is_utf8($str);
Stylistically, I'm inclined to push for the second. If performance is an issue though, you'd do well to consider using the first.
if (function_exists("sin")) {
function baz($farfs) {
print "I am the first baz";
}
} else {
function baz($farfs) {
print "I am the second baz";
}
}
function blarg($fgar) {
if (function_exists("sin")) {
print "I am the first blarg";
} else {
print "I am the second blarg";
}
}
for ($i=0;$i
I ran this on my workstation here, and found that the aggregate time of calls to baz took anywhere from 50-75% of the aggregate calls to blarg, depending on whether the function being tested actually exists.
Here are the actual numbers:
function_exists("foobar")
blarg: 36.64 ms
baz: 14.71 ms
function_exists("sin")
blarg: 35.24 ms
baz: 23.59 ms
The only difference between these two functions is the conditional and the two extra characters in the output. Interestingly enough, the 10001 calls to function_exists only take 0.18 and 0.11 ms respectively on the two tests. I'm wondering if there is some function call overhead not being accounted for in either profile.
As for style though, I really dislike the first. Defining a function by name in two different places seems like a shady thing to do, especially when relying on the oddness in PHP that makes function definitions not performed in global scope affect global scope anyway. On the other hand, my biases just might be showing, and the rest of the PHP community might not have a problem with relying on the PHP interpreter as a sort of preprocessor in this instance.
shrug Such are the matters of style.
By default, go always with the most readable solution. If that particular piece of code turns out to be a significant drag (measured, not assumed) on your application, then you optimize it.
I'll apologize in advance for what's most likely pretty ugly PHP, but I'd do something more like:
if (function_exists('mb_detect_encoding')) {
function is_utf8_mb($str) {
// do stuff using the mb* libraries
}
}
function is_utf8_manual($str) {
// do stuff manually
}
if (function_exists('is_utf8_mb')) {
function is_utf8($str) {
is_utf8_mb($str)
}
} else {
function is_utf8($str) {
is_utf8_manual($str)
}
}
That is: an is_utf8 variant will exist in the execution environment dependent only on if it can work in that environment. Each variant is in a code block of the minimal size needed to determine if that variant should be loaded, and to perform its function. The main reason is that I think the smaller the amount of space you need to write your function, the easier it is for a reader to build an understanding of the function's behavior. Your eyes have to travel less, you have to scroll less, there are generally fewer of those trivial frustrations involved in understanding a function for the first time. The second reason is that it provides a better way of testing your code - you can more easily automate a check that the is_utf8 variant routines are producing the same result when you can access all of them at the same time.
There are two aspects at play here: performance (don't pay for what you don't need), and readability.
As many wise posters say: don't bother about performance until it's proven to be a problem.
But concerning readability, in my opinion, a function should show as little layers of responsibility as possible. Functions that do exactly one thing are easiest understood.
Your question is actually about 'how should I mix two responsibilities':
what: detect the presence of a library, and 'dispatch' to the correct code block
how to use the library vs. how to do without.
That's why I would really create two 'layers': one layer dispatching to the appropriate function, and another layer containing 'code blocks', wrapped in a function with the proper name.
And then you still have the choice whether to do the dispatching explicitly, or to use PHP's possibility to declare functions on-the-fly.
// functionality: defines how to detect utf8 encoding
//
function is_utf8_mb( $arg ) {
... // using the mb library
}
function is_utf8_bare( $arg ) {
... // hand coded
}
// dispatching layer: decide what library to use
//
// option 1: define on-the-fly
function define_utf8_function() {
if( function_exists('mb_detect_encoding') ) {
function is_utf8( $arg ) { return is_utf8_mb( $arg ); }
} else {
function is_utf8( $arg ) { return is_utf8_bare( $arg ); }
}
}
// option 2: check the dispatching on each function call
function is_utf8_runtimedispatch( $arg ) {
if( function_exists('mb_detect_encoding') )
return is_utf8_mb( $arg );
else
return is_utf8_bar( $arg );
}

Something like overloading in PHP?

I'd like to accomplish something like this: Call a method, say "turn", and then have "turn" applied differently to different data types, e.g., calling "turn" with a "screwdriver" object/param uses the "turnScrewdriver" method, calling "turn" with a "steeringWheel" object/param uses the "turnSteeringWheel" method, etc. -- different things are being done, but they're both called "turn."
I'd like to implement this so that the calling code needn't worry about the type(s) involved. In this example, "turn" should suffice to "turn" a "screwdriver", "steeringWheel", or whatever might need to be "turned."
In C++ I'd do this with overloading -- and C++ would sort things out based on the datatype/signature -- but this doesn't work in PHP.
Any suggestions as to where should I begin? A switch statement is obvious, but I'm thinking there must be a (more elegant) OO solution. No?
TIA
I read davethegr8's solution but it seems one could do the same thing with stronger typing:
<?php
interface Turnable
{
public function turn();
}
class Screwdriver implements Turnable
{
public function turn() {
print "to turning sir!\n";
}
}
class SteeringWheel implements Turnable
{
public function turn() {
print "to everything, turn, turn turn!\n";
}
}
function turn(Turnable $object) {
$object->turn();
}
$driver = new Screwdriver();
turn($driver);
$wheel = new SteeringWheel();
turn($wheel);
$obj = new Object(); // any object that does not implement Turnable
turn($object); // ERROR!
PHP does permit you to use a type hint for the parameter, and the type hint can be an interface name instead of a class name. So you can be sure that if the $object implements the Turnable interface, then it must have the turn() method. Each class that implements Turnable can do its own thing to accomplish turning.
I think this will work...
function turn($object) {
if(method_exists($object, 'turn'.ucwords(get_class($object))) {
$fname = 'turn'.ucwords(get_class($object));
return $object->$fname();
}
return false;
}
You need to check the PHP Manual for instructions here

Categories