Can someone please explain how overloading in PHP works? The manual doesn't do a very good job of it. I'm still thinking of overlaoding in the Java sense, but I know overloading in PHP is a completely different animal. All the PHP manual says is that overloading provides a mechanism for adding new properties and methods to a class at runtime, but it doesn't explain how PHP achieves this. Thanks in advance. Rylie
All the PHP manual says is that overloading provides a mechanism for adding new properties and methods to a class at runtime, but it doesn't explain how PHP achieves this.
The very manual page you linked to explains how the thing that PHP calls "overloading" works. You're pretty correct in that it has little to do with what the entire rest of the world calls overloading. In fact, the manual page says right at the top:
PHP's interpretation of "overloading" is different than most object oriented languages. Overloading traditionally provides the ability to have multiple methods with the same name but different quantities and types of arguments.
PHP has reserved a handful of special method names that you can optionally define in a class. They fall into two categories:
__get, __set, __isset and __unset are called when an instance variable (object property) is fetched, set, checked for existence, or unset respectively. All receive the name of the property as the first argument, and __set receives the new value as the second argument. These methods are only called when either the property does not exist or can not be accessed from the caller's scope (i.e. protected/private). It's worth noting that without these methods, PHP will silently create new instance variables on demand, when asked to.
__call and __callStatic are called when a method is called that, again, doesn't exist or can't be accessed from the caller's scope. The former is called for instance methods, the latter for class methods. The first argument is the name of the method called, and the second is an array of the arguments, by value (references are dereferenced).
These functions allow you to simulate adding methods to a class/instance after creation, though their use is clunky and awkward. Further, using them breaks autocomplete in IDEs.
Using anonymous functions might seem like a natural complement to this functionality, but it is currently not possible to bind an the instance ($this) to one at run time. This functionality was removed during the 5.3 beta because it couldn't be made clear and obvious. This has been corrected in PHP's current trunk, but it's unknown when the trunk will be stabilized for release.
Related
In PHP, when defining classes; there's often a __construct (constructor) and a __destruct (destructor) implemented into an object when it is created and 'destroyed'.
In PHP, an object is 'destroyed' when it stops being used
Now, how is that helpful? How is it used exactly and in which cases will it become handy in a programming language such as PHP?
"When an object is no longer needed it has to be deleted. Objects created within functions as local variables. (...) Whenever an object is deleted its destructor member function is called. Its understandable why constructors are so important, objects must be properly initialised before they can be used, but is it really necessary to have a special member function that gets called when the object is about to disappear?
In many cases the answer is no, we could leave the compiler to invent a default no-op one. However suppose your object contained a list of detector hits from which it was built. Without going into detail, its likely that this would be some kind of dynamic object owned by the object and accessed via a pointer. Now when it comes time to delete the object, we want this list to be deleted, but probably not the hits that it points to! The compiler cannot possibly know, when it comes across a pointer in an object whether it points to something owned by the object and to be deleted as well, or simply something related to, but independent of, the object.
So the rule is If an object, during its lifetime, creates other dynamic objects, it must have a destructor that deletes them afterwards. Failure to tidy up like this can leave to orphan objects that just clog up the memory, something that is called a memory leak. Even when a default is acceptable, its a good idea to define a destructor..."
See more: OO Concept: Constructors & Destructors
What is the difference between __get__() and __getattr__() in Python? I come from a PHP background, where there is only __get(). When should I use which function?
I've been trying to figure this out for a while. I see plenty of questions like this one, asking about the difference between __getattr__() and __getattribute__(), though.
First an foremost, PHP does not have an equivalent to Python's __get__() – not even close! What you are looking for is most definitely __getattr__().
I come from a PHP background, where there is only __get__
PHP has a magic method called __get(), which is invoked whenever you are trying to access a property that does not exist.
A short list of non-equivalents
First, let's clear some things up:
PHP does not have an equivalent to Python's __get__()
PHP does not have an equivalent to Python's __getattr__()
PHP does not have an equivalent to Python's __getattribute__()
Python does not have an equivalent to PHP's __get()
(And for all setter methods respectively.)
Contrary to Achim's assumption, __get() does not do the same as Python's __getattr__()!
Python does not distinguish between methods and properties, but PHP does, which is why PHP has a second method: __call().
__call() is executed whenever you try to invoke a method on an object that does not exist. Python does not have an equivalent for this, because a method is simply an object (attribute) that is callable.
An example in PHP:
<?php
$obj = new stdClass();
($obj->test)();
In Python, this would fail with an AttributeError. In PHP, however, this does not even compile:
Parse error: syntax error, unexpected '(' on line 4
Compare this to Python:
obj.method()
# is eqvuivalent to:
(obj.method)()
This is an important difference. We conclude that the way PHP and Python think about calling methods are completely different.
PHP's "call awareness"
PHP's obj knows that you call a method
you get to handle calls to non-existing methods explicitly on the object you call on
this is because PHP's expression model is very inconsistent (PHP 5.4 is a small step forward though)
but Python's obj does not.
This makes it possible for PHP to have obj.does_not_exist to evaluate to 3, but obj.does_not_exist() to 5.
To my knowledge, it's impossible to do so in Python. (This would allow us to describe PHP's inconsistency as a feature.)
Thus, we get to extend our "not equivalent"-list by one bullet point:
Python does not have an equivalent to PHP's __call()/__callStatic()
Summing it up
PHP provides two separate mechanisms:
__get() for non-existing properties
__call() for calls to non-existing methods
Python has only one mechanism, because it does not distinguish between properties and methods, as far as it is concerned they are all attributes.
__getattr__() is invoked, when an attribute does not exist.
obj.non_existing() is not special "call syntax", it's an expression to which the call operator () is applied: (obj.__getattr__("non_existing"))()
Disclaimer: __getattr__() is not always called when an attribute does not exist. __getattribute__() takes the highest precedence in the lookup chain and may thus cause __getattr__() to be ignored.
Descriptors
__get__() in Python is something completely different from what has been addressed above.
The documentation describes descriptors to be "a descriptor is an object attribute with “binding behavior”". I can sort of form an intuitive understanding what "binding behavior" is supposed to mean, but only because I already understand what descriptors do.
I would choose to describe descriptors as "self-aware attributes" that can be shared across multiple classes.
Let me explain, what I mean by "self-awareness". Such attributes:
know when they are being accessed or read from
know when they are being written to
know whom they are read/written via
know when they are deleted
These attributes are independent objects: the "descriptor" objects, i.e. objects that adhere to the so called "descriptor protocol", which defines a set of methods along with their corresponding signature that such objects can implement.
An object does not own a descriptor attribute. In fact, they belong to the object's corresponding class (or an ancestor thereof). However, the same descriptor object can "belong" to multiple classes.
Note: "whom they are read via", what is the proper way to refer to obj in obj.attr? I would say: attr is accessed "via" obj.
You will find detailed documentation for all those methods here.
Coming from PHP, you should first make yourself familiar with the Python object model. It's much richer than PHP, so you should not try to map your PHP knowledge 1:1 to Python. If you want to develop PHP, use PHP. If you want to develop in Python, learn Python.
Coming back to your original question: __getattr__ is probably the function which does the same as the __get function in PHP. __get__ in Python is used to implement descriptors. Details about descriptors can also be found in the documentation I mentioned above.
Is there an Actionscript equivalent to PHP's __get() and __set() magic methods? I want to be able to override the behavior of getting/setting member variables.
There is no such thing, unfortunately.
All you can do is check for the existence of a specific property, by using either
myObject.hasOwnProperty (name)
on simple Objects or some variant of describeType() for Class instances, for example
describeType(myObject).accessor
to get an XMLList of all accessor methods or
describeType(myObject).variable
to get an XMLList of all variables.
describeType(), however, is quite expensive in terms of performance, so it pays to have some sort of type hash map to store the lists for each type and do lookups for types that have already been described once.
You could also use try/catch blocks around the parts where undefined properties might be accessed, but this also "eats" away a lot of performance, if many errors are thrown.
Found it.
Extending the Proxy class allows you to solve this problem.
Still on the PHP-OOP training wheels, this question may belong on failblog.org. =)
What are the benefits of method chaining in PHP?
I'm not sure if this is important, but I'll be calling my method statically. e.g.
$foo = Bar::get('sysop')->set('admin')->render();
From what I've read, any method which returns $this is allowed to be chained. I just learned this is new in PHP5. Seems to me there may be speed benefits if I don't have to instantiate a whole new object (calling it statically) and just select the few methods I need from the class?
Do I have that right?
There are no significant performance benefits to using either approach, especially on a production server with byte code cache.
Method chaining is just a shorter way of writing things. Compare with the longer version:
$foo = Bar::get('sysop');
$foo -> set('admin');
$foo -> render();
It does have some quirks, though: a typical IDE (such as Eclipse) can auto-complete your code in the longer version (as long as the type of $foo is known) but needs you to document the return type of all methods to work in the short version.
It still instantiates an object; it's just never assigned to a variable. Basically, you're just calling the methods of an anonymous object.
I think any cycle-savings would be negligible, but I think the unassigned objects would be freed immediately after this line of code, so you may have some memory savings (you could accomplish the same by setting assigned objects to null when you were done with them).
The main reason people use method chaining is for convenience; you're doing a lot in one line of code. Personally, I think it's messy and unmaintainable.
if I don't have to instantiate a whole
new object (calling it statically) and
just select the few methods I need
from the class?
Wrong! To return $this, the class has to be instantiated.
I am new to object oriented programming and writing some of my first classes for a PHP application.
In some of the simpler classes, I declare a function __construct(), and inside of that function, call certain class methods. In some cases, I find myself instantiating the class in my app, and not needing to do anything with the resultant object because the class's __construct() called the methods, which did their job, leaving me nothing left to do with the class.
This just doesn't feel right to me. Seems goofy that I have a new object that I never do anything with.
Again, I'll stress this is only the case for some of my more simple classes. In the more complicated ones, I do use class methods via the object and outside of __construct().
Do I need to rethink the way I coding things, or am I ok?
Well, the constructor is used to create a new instance of a class, and to do any necessary setup on that class. If you're just creating the class and leaving it, that does seem a bit of a waste. Why not, for instance, use static functions in the class as an organizational tool and just call them(or a function that calls them) instead of constructing a new instance that you'll never use?
This just doesn't feel right to me. Seems goofy that I have a new object that I never do anything with.
Yes, that should raise a red flag.
In general, you should not let constructors have any side effects; They are meant for initialising the state of the object - not for anything else. There are of course exceptions to this rule, but in general it's a good guide line. You should also abstain from doing any heavy calculations in the constructor. Move that to a method instead.
Side effects are many things - Changes to global variables or static (class) variables; output to the environment (For example calls to print(), header() or exit()); calls to a database or other external service and even changes to the state of other objects.
A side effect free function is also called a "pure" function - as opposed to a procedure, which is a function that has side effects. It's a good practise to explicitly separate pure functions from procedures (and perhaps even label them as such).