php static function inheritance - php

I want to define a base class with static functions and an extended class which calls the static methods of its parent. As an example a base class for arrays cArray with a static method Length($arr), so a static method call
cArray::Length($myArray);
Then I want to write an extended class xArray and use it as follows:
$objArr = new xArray($arr);
$objArr->Length();
My question is whether this is ever possible. I tried many codes but all get failed for different reasons.

You should just be able to call the method statically. It will automatically call the method in the parent class, unless you have redefined the same method in the child class.
xArray::Length($arr);

To put this into code:
class cArray {
public static function Length($myArray) { ... }
}
class xArray extends cArray {
...
public function Length() {
parent::Length($this->arr);
}
}
While PHP will let you do this, it's a terrible idea. When extending classes, you should not change the method signatures fundamentally. Here you're overriding the static method cArray::Length which takes one argument with the non-static xArray::Length which takes no argument. That's a fundamentally different function and thereby a bad class structure. PHP will point this out to you if you enable strict errors.
You need to rethink your approach. There's no reason the method needs to be static in the base class and no reason it needs to change its signature in the extended class.

Related

How to prevent inheritance of static methods? [duplicate]

So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}

Accessing properties from a class in an inherited static method in PHP

I have a number of PHP classes inheriting a single base class. This base class offers up a static method, let's call it methodA() that can be overridden in each class, but in practice won't be overridden very much. Each class has a static variable, let's call it name that is different, but methodA() needs to be able to act based on name differently for each class. I'm new to object oriented PHP, so I'm not exactly sure how best to do this.
In Java I would make a property on the base class and then define it in the constructor method which I would then call via super(), but I'm not sure how best to do this based on static data. Am I on the right track? What would be the best way to accomplish this?
This answer was thanks to #AlexBlex.
PHP provides a feature called Late Static Bindings that allow exactly this behavior.
As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance.
In the example provided in the question, the way to do this would be as such:
class Base {
public static function methodA() {
return static::$name;
}
}
class A extends Base {
public static $name = "Apple";
}
class B extends Base {
public static $name = "Box";
}
You can then call the function as such with the expected results:
echo(A::methodA()); // "Apple"
echo(B::methodA()); // "Box"
This example runs in PHP 7.

what is use of public function with body in abstract class of php?

I have create one abstract class and declare two public functions and one abstract function.
After that I have created body for public function in abstract class but when I extending this class to Another class what the method body does not call then I want to know what is use of public methods with body class.
<?php
//declare abstract class
abstract class Test {
// declare method 1 with body
public function method1()
{
echo "hello"; //what is use of this code here
}
public function method2()
{
$this->method3();
}
abstract public function method3();
}
//extended abstract class to another class
class AnotherTest extends Test{
public function method1(){
echo "5+9"/2;
}
public function method3(){
echo 2+9;
}
public function method2()
{
echo "just for testing";
}
}
$obj = new AnotherTest();
$obj->method1();
echo nl2br("\n");
$obj->method3(9,10);
echo nl2br("\n");
$obj->method2();
?>
Writing a method body for a method of a base class provides a "default" behavior for that method on any subclasses that don't override the method.
For any (non-final) public or protected method of a base class you can do one of the following:
Accept that default behavior without modification by not defining a method with the same name in a subclass
Override and wrap that behavior by defining a new method with the same name that calls parent::methodName() in a subclass
Override and replace that behavior by defining a new method with the same name that does NOT call parent::methodName() in a subclass
The major benefit of code written like this is that it takes advantage of Polymorphism to dispatch generic method calls to specific implementations. Defining a method body instead of leaving it abstract just provides a default behavior. As this is a very abstract object-oriented programming concept, it is hard to set up an example that is both simple and not trivial. Best to look at popular codebases such as the Laravel Framework or one of the various Symfony components for examples of this concept in action.
Generally speaking you would not normally override every abstract method. If you are then you're doing something wrong and need to refactor.
Also, having the abstract (or any extended class) gives you the ability to call parent::function() which will let the parents method run then you can do your current classes additional logic.
In the end this is the basis for Polymorphism simple explanation a child class can extend a parent but act differently by changing how methods behave.
Bluntly your "Test" are just bad examples because in those cases you're right the abstract bodies are almost pointless.

How to prevent usage of public parent methods in child instance in PHP?

So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}

Calling static method non-statically

I have a child class that extends a class with only static methods. I would like to make this child class a singleton rather than static because the original developer really wanted a singleton but used static instead (obvious because every method in the static class calls the Init() function (basically a constructor)).
Most of the methods in the parent don't need to be overwritten in the child, but I would like to avoid having to write methods like this:
public function Load($id)
{
return parent::Load($id);
}
when I would prefer not to overwrite the method at all and just use:
$child->Load($id);
Is it possible to call a static method non-statically? Is it possible to extend a static object with an instance object? I know I can try it and it will likely work (PHP is very forgiving), but I don't know if there is anything I should be concerned about.
Can you inherit static methods?
Yes
Can you override static methods?
Yes, but only as of PHP 5.3 do they work as you would expect: http://www.php.net/manual/en/language.oop5.static.php (ie. self binds to the actual class and not the class it's defined in).
Is it possible to call a static method non-statically?
Yes, but will lose $this. You don't get a warning (yet) but there also isn't really a reason to call it the wrong way.
Two part answer.
First, about the titular question: calling a static method non-statically is perfectly fine; #SamDark's comment is correct. It does not produce a warning, nor does it cause any kitten murdering. Try it:
<?php
class test {
public static function staticwarnings(){
echo "YOU ARE (statically) WARNED!\n";
}
}
error_reporting(E_ALL);
$test = new test();
echo "\n\ncalling static non-statically\n";
$test->staticwarnings();
If you had an instance reference, $this, in that static method, then you would get a fatal error. But that is true regardless of how you call it.
Once again, there isn't a warning, nor any kitten killed.
Second part of the answer:
Calling an overridden parent function from an overriding child class requires something called "scope resolution". What the OP is doing in their method is NOT calling a static method. (Or at least, it doesn't have to be; we can't see the parent implementation). The point is, using the parent keyword is not a static call. Using the :: operator on an explicit parent class name is also not a static call, if it is used from an extending class.
Why is that documentation link so strangely named? It's literally Hebrew. If you've ever run into an error related to it, you might have observed the delightfully-named parser error code T_PAAMAYIM_NEKUDOTAYIM.

Categories