Reputation: 4810
I'm a bit confused on the proper way to call common methods within abstract classes. Using the following code:
abstract class Transaction {
abstract public function process();
abstract public function set_status();
protected function get_valid_statuses() {
return array(
'pending',
'approved'
);
}
}
class Purchase extends Transaction {
public function process() {
}
public function set_status( $status ) {
//check against valid statuses
$valid = Transaction::get_valid_statuses();
.......
}
}
Obviously this code is far from complete, but should suffice for this example. I am wondering why this works, because I have tested it. Within my Purchase class, when using the set_status method, I am calling the get_valid_statuses()
method using the Scope Resolution Operator that you would typically use for a static method. I would have assumed to call the method using:
$valid = Transaction->get_valid_statuses();
But I guess this would not work because the class was never actually instantiated. Can someone provide some clarification please. I was unable to find an understanding from the PHP documentation on abstract classes or the Scope Resolution Operator.
Thanks!
Upvotes: 1
Views: 2093
Reputation: 70863
Using that ::
operator (scope resolution operator) does not always trigger a STATIC method call.
In your case, it does. You are using a classname. But there are special keywords that do not trigger a static call: self
, parent
, static
.
Besides that, there is also the variable that refers to the current, own object: $this
.
So whenever you inherit a class which brings it's own methods, you could always treat them like they are in your current class, and call $this->get_valid_statuses()
. This dynamically checks for the presence of that function in the current class, or any parent class or parent parent class in descending order, and calls the first one found.
If you want to make sure you call the function of the parent class, use parent::get_valid_statuses()
. If you want to make sure you call the method of the CURRENT class, use self::get_valid_statuses()
.
The static
keyword plays an important role when inheriting static methods in classes - but because static methods usually are more evil than helping you, I'd like to point to the manual only.
What to do when inheriting a class? It depends. $this
works. It also allows to override that get_valid_statuses()
in the current class and extend it.
parent::get_valid_statuses()
should really only be called if your Purchase
class overrides get_valid_statuses()
and wants to get the statuses from the parent class. In this case you cannot call $this->get_valid_statuses()
, because that would again call the method in the same class, leading to a never ending loop. So parent::
and $this->
are the most used prefixes.
Upvotes: 0
Reputation: 29462
Turn on error reporting an you will see Strict error:
Non-static method Transaction ::get_valid_statuses() should not be called statically
This error is present in all 5.x php versions - so it does work for backward compatibility reasons. Back in dark times of php4 there was no way to declare static methods inside class, so all methods were declared simple as function foo(){ }
You can learn about static methods here. To put it simple, you do not need to instantiate class before calling this method (and you can not instantiate it because of abstract
keyword), but you call it by using class name and scope resolution operator.
This also works because there is no reference to current object ($this
) inside this method. If you change this method body to reference one of its properties / methods using $this
, you will end with fatal error.
Upvotes: 1
Reputation: 13283
The method is not static so you should not use the static method operator (::
). Also because Purchase
inherits the abstract class it will automatically get all its methods, which can be used using $this
:
$valid = $this->get_valid_statuses();
Upvotes: 0
Reputation:
Abstract classes can't be instantiated but methods (not abstract) can be called as static methods.
Anyway, it's very bad code style - please consider to not use it.
Upvotes: 0