Which one is the best way to extend a method in a class which has a body?
class one
{
public function methOne($var)
{
// Something here
}
public function methTwo($var)
{
// Something here
}
}
class two extends one
{
public function methTwo($var, $varTwo)
{
if($varTwo === true)
parent::methTwo($var);
else
return 100;
}
}
In the example above, is there a way I can force class two to extend methTwo considering the parent methTwo has a logic I'll reuse in some condition?
I was thinking to abstract the class and the method, but I cannot abstract a method which is not empty.
You can make the method protected in the base class. If a subclass doesn't override it, callers will get an error because they can't access the name. But subclasses can call it from their overriding method, because protected names are accessible to subclasses.
Related
I just have a simple question here... I was working on developing a forum application for my website, and while updating some of the old methods I used (my old code is horrid) I came across - not for the first time - OOP devices.
I have quite a few classes that my system uses, and redefining the same function(s) for them over and over, so I decided to create a base class that would carry the functionality.
I've been trying to use require() on the base class then extend the class off of it...
<?php
require(//path to base class);
class User extends BaseClass {
// code
}
?>
But I don't know how to check if it's there, and it doesn't seem to be inheriting the base class's only function...
public function __get($what) {
if(property_exists($this, $what)) {
return $this->{$what};
} else {
return null;
}
}
Since when I try to retrieve a variable from the User class (e.g. $user->Username) it returns NULL. The variable is marked as private in the class, but before I tried to do inheritance that wasn't an issue.
It sounds like you are wanting to get after your variables in your parent class but do not want to use getter methods to do so. Marking these variables protected will indeed allow your child classes access to those properties, but in cases where you want your base class to enforce processing before setting/getting, marking the properties protected will not cut it.
In your case it sounds like you are marking your variables protected as a workaround. However you can still use private variables in your base class and allow access to them in your child classes as follows:
class BaseClass
{
private $strValue = "We the people....";
public function __get($what)
{
if(isset($this->{$what})) {
return $this->{$what};
}
return null;
}
}
class ChildClass extends BaseClass
{
private $intValue = 255;
public function __get($what)
{
if(isset($this->{$what})) {
return $this->{$what};
} else if(parent::__get($what) != null) {
return parent::__get($what);
}
return null;
}
}
//Try it out
$child = new ChildClass();
var_dump($child->strValue); //"We the people...."
var_dump($child->intValue); //255
In this example the BaseClass uses the __get() magic method to lookup its own properties and the ChildClass overrides it to do the same. In the ChildClass if it cannot find a requested property, then it diverts to the parent's version.
As long as you don't override your properties you can use private variables throughout and access them as if they were public outside of your class scope.
just use
class_exists() to make sure your class is there.
What is the best of calling a method in child class. My IDE always shows Errors if i try to call the method directly.
class Base
{
public function DoIt()
{
$this->Generate(); //How to check if child implements Generate?
}
}
class Child extends Base
{
protected function Generate()
{
echo "Hi";
}
}
Simply put, you don't do this. It is very bad design: base classes should never assume anything about their descendants other than that they implement the contracts the base itself defines.
The closest acceptable alternative would be to declare abstract protected function Generate() on the parent so that it knows that all derived classes implement it. Of course this is not meant to be a mechanical solution: you should only do it if Generate is meaningful for all descendants of Base.
The issue is that your parent class doesn't define a Generate() method that a child class can override; you have to explicitly define this by creating an abstract method:
// class with at least one abstract method is
abstract class Base
{
public function DoIt()
{
$this->Generate();
}
// child classes MUST implement this method
abstract protected function Generate();
}
You can loosen the requirements by creating an empty implementation in the parent class:
class Base
{
public function DoIt()
{
$this->Generate();
}
// child classes MAY implement this method
protected function Generate() {}
}
In other OO languages like Java we can override a function, possible using keywords/annotations like implements, #override etc.
Is there a way to do so in PHP? I mean, for example:
class myClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
I want user to implement their own myClass::reImplementThis() method.
How can I do that in PHP? If it is possible, can I make it optional?
I mean, if the user is not implementing the method, can I specify a default method or can I identify that the method is not defined (can I do this using method_exists)?
<?php
abstract class Test
{
abstract protected function test();
protected function anotherTest() {
}
}
class TestTest extends Test
{
protected function test() {
}
}
$test = new TestTest();
?>
This way the class TestTest must override the function test.
Yes, there is. You have the option to override a method by extending the class and defining a method with the same name, function signature and access specifier (either public or protected) it had in the base class. The method should not be declared abstract in the base class or you will be required to implement it in the derived class. In you example it would look something like this:
class MyClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
class MyDerivedClass extends MyClass {
public static function reImplmentThis() { //the method you want to call
}
}
If the user does not overrides it, MyDerivedClass will still have a reImplmentThis() method, the one inherited from MyClass.
That said, you need to be very careful when invoking extended static methods from your derived class to stay out of trouble. I encourage you to refactor your code to extend instance methods unless you have a very specific need to extend static classes. And if you decide there is no better way than extending static classes please be sure to understand Late Static Binding pretty well.
Yes, its possible to check if the method is implemented or not and get a whole lot more of information about a class using PHP Reflection.
This touches on several OOP subjects.
First, simply overriding an method declared in a parent class is as simple as re-declaring the method in an inheriting class.
E.g:
class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
}
class Tommy extends Person {
public function greet(string $whom = "everyone") {
echo "Howdy $whom! How are you?";
}
}
$a = new Tommy();
$a->greet('World');
// outputs:
// Howdy World! How are you?
If on the overriding method you wan to reuse the logic of the overriden one, it's just a matter of calling the parent's method from the extending class::
class Tommy
{
public function greet(string $whom)
{
// now with more emphasis!!!
echo parent::greet(strtoupper($whom)) . "!!!!";
}
}
Now Tommy::greet() calls Person::greet(), but modifies the result before returning it.
One thing to note is that overriding methods have to be compatible with the overriden one: the method visibility can't be more restrictive than the original one (it's OK to increase visibility), and the number and type of required arguments can't conflict with the original delcaration.
This works, because the type of the arguments does not clash with the original, and we have less required arguments than on the parent:
class Leo extends Person {
public function greet(string $whom = "gorgeous", string $greet = "Whatsup" ) {
echo "$greet $whom. How are you?";
}
}
But this doesn't, since there are additional required arguments. This would make impossible to switch the original class for this one transparently, and thus would throw a Warning:
class BadBob extends Person {
public function greet(string $whom, string $greet ) {
echo "$greet $whom. How are you?";
}
}
Additionally, you mention in your question that "this method should be overriden by the user". If you require client classes to actually implement the method, you have a couple of options:
Abstract classes & methods
These are methods where the implementation is left empty, and that extending classes have to implement to be valid. In we changed our original class Person to:
abstract class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
public abstract function hide();
}
Since now the class contains an abstract method, it needs to be declared as an abstract class as well.
Now it is not possible to instantiate Person directly, you can only extend it in other classes.
Now all our existing Person extending classes would be wrong, and trying to execute the previous code would throw a fatal error.
An example of a valid class extending Person now would be:
class Archie extends Person {
public function hide() {
echo "Hides behind a bush";
}
}
Any class that extends Person must declare a public hide() method.
Interfaces
Finally, you mention interfaces. Interfaces are contracts that implementing classes have to fulfill. They declare a group of public methods without an implementation body.
E.g.:
interface Policeman {
public function arrest(Person $person) : bool;
public function help($what): bool;
}
Now we could have class that extended Person and implemented Policeman:
class Jane extends Person implements Policeman {
public function hide() {
echo "Jane hides in her patrol-car";
}
public function arrest(Person $person): bool{
// implement arrest method
return false;
}
public function shoot($what): bool {
// implements shoot() method
return false;
}
}
Importantly, while it's possible to extend only one class (there is no multiple inheritance in PHP), it is possible to implement multiple interfaces, and the requirements for each of those have to be fulfilled for the class to be valid.
Is there anyway (or a pattern) to enforce a call to a parent method?
I have an abstract class like so:
abstract class APrimitive{
public function validate(){
//Do some stuff that applies all classes that extend APrimitive
}
}
Then I have classes that extend upon the APrimitive "base":
class CSophisticated extends APrimitive{
public function validate(){
//First call the parent version:
parent::validate();
//Then do something more sophisticated here.
}
}
The problem is that if we come back to the code in a few months time, and create a few more classes like CSophisticated with a validate() method, there is a possibility that we might forget to make a call to parent::validate() in that method.
Note that some CSophisticated classes may not have the validate() method, so the parent version will be called.
I understand that it is possible to just put in a comment somewhere, to remind the programmer to call parent::validate(), but is there a better way? Perhaps an automated way to throw an exception if the call to parent::validate() was not made in the validate() method would be nice.
You can enforce the call with the following:
abstract class APrimitive{
final public function validate(){
//do the logic in validate
overrideValidate();
}
protected function overrideValidate(){
}
}
class CSophisticated extends APrimitive{
protected function overrideValidate(){
}
}
Now only calls to validate are permitted, which will in turn call your overridden method. The syntax may be a little off (PHP is not my language of choice) but the principle is applyable to most OOP languages.
FURTHER EXPLANATION:
abstract class APrimitive{
public function validate(){
echo 'APrimitive validate call.';
overrideValidate();
}
protected function overrideValidate(){
}
}
class CSophisticated extends APrimitive{
protected function overrideValidate(){
echo 'CSophisticated call.';
}
}
CSophisticated foo;
foo.overrideValidate(); //error - overrideValidate is protected
foo.validate(); //
Output:
APrimitive validate call.
CSophisticated call.
The function call basically does the following:
foo.validate() -> APrimitive.validate() -> ASophisticated.overrideValidate() (or APrimitive.overrideValidate() if it wasn't overriden)
You're looking for The Template Method pattern.
This pattern allows you to modify an operation in some way through sub-classing but ensures that the base class is always involved.
class Base {
//declared final so it can't be overridden
public final function validate() {
//perform base class operations here
//then forward to the sub class
$this->doValidate();
//do some more base class stuff here if needed
}
//override this method to alter validate operation
protected function doValidate(){
//no-op in base
}
}
class Sub {
protected function doValidate() {
//if required
//make the sub-class contribution to validate here
}
}
In the project my team is currently working on, we're modifying a commercial PHP application. The app is strewn with code where a parent class checks for and works with a property that doesn't exist in the parent class, like so:
class A
{
function doSomething()
{
if (property_exists($this, 'some_property'))
{
$this->some_property = $_REQUEST['val'];
}
}
}
class B extends A
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}
We feel vaguely dirty having to modify this code; is this proper design? What are the ways (other than the obvious) something like this can be avoided?
You might consider abstracting the parent class. So the methods that the children must have are declared in the parent, but not implemented.
Relying upon methods that must exist in a subclass is not dirty, as long as you can declare them as abstract.
However, it is not good practice to rely on and manipulate properties outside of a class. It's best to use abstract setters, like this:
abstract class A
{
abstract protected function setSomeProperty($data);
public function doSomething()
{
$this->setSomeProperty($_REQUEST['val']);
}
}
class B extends A
{
private $some_property;
public function doSomething()
{
parent::doSomething();
}
protected function setSomeProperty($data)
{
$this->some_property = $data;
}
}
More info here: PHP Class Abstraction
However, since you said you're not allowed to modify the parent class, I would suggest making a subclass that acts as an Adapter to what the parent class "expects", and a class that you're able to design "properly".
You can create a virtual method hook in the parent class which can later be overridden by children.
I think it's more neat to create a sub-class, where all members have function doSomething(). In that case you don't create a not-working function in a parent class (with eventual hacks), but still have the general "super-function".
class A
{
}
class C extends A {
protected $some_property;
function doSomething()
{
$this->some_property = $_REQUEST['val'];
}
}
class B extends C
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}