Can php call a static alias? - php

In php, is it possible for a method in a parent class to use an alias in a child class from within an instance of the child class?
Parent class:
class ParentClass
{
public function getNewFoo()
{
return new Foo();
}
}
Child class:
use My\Custom\Path\To\Foo;
class ChildClass extends ParentClass
{
}
Code:
$child = new ChildClass();
return $child->getNewFoo();
I would like this code to return a new instance of My\Custom\Path\To\Foo() rather than a new instance of Foo().
I realize I can store the desired path to Foo in a class property, or I can simply instantiate the desired Foo in the child class. However, both of these seem redundant considering the path is already stored in the use statement in the child class.

You're asking a lot of PHP here. It's supposed to know that your use statement is going to impact something in a completely different class, in a completely different file, just because?
If PHP did that by default it would cause a lot of very strange problems for people. Re-define the method, or as you point out, store that property in the class itself.
I think a lot of developers would expect, or at least prefer that PHP behave the way it does.
It sounds like what you need here is a factory function that can be redefined in the subclass to behave differently, or in other words, that getNewFoo() should be overridden in the subclass to use the alternate version.

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();
}

PHP: change a method behavior

I have an object with some protected fields and a method that uses them. The method doesn't do exactly what I need it to do, but I cannot change the original code since I am writing an add-on.
Is it somehow possible to extend the class and override the method so that I could call it on predefined objects of the original class? I thought about monkey patching but apparently it is not implemented in php.
You can override a method by extending the parent class, initiating the new class instead of the parent class and naming your method exactly the same as the parent method, that was the child method will be called and not the parent
Example:
class Foo {
function sayFoo() {
echo "Foo";
}
}
class Bar extends Foo {
function sayFoo() {
echo "Bar";
}
}
$foo = new Foo();
$bar = new Bar();
$foo->sayFoo() //Outputs: Foo
$bar->sayFoo() //Outputs: Bar
I hope below stategy will be works. asume that class is Foo and method is bar(). for override bar() method you have to make customFoo class as mentioned below.
class CustomFoo extends Foo{
public function bar(){
parent::bar();
}
}
I dont know actually what you need because you dont have explained in detail. Still I have tried my best. :)
Try creating a child class that extends the base or parent class that the object currently derives from.
Create a new method with exactly the same name as the method in the Parent class and put your logic in there.
Now instantiate your object from your new class, you would have succeeded in overriding that particular method and still have access to the methods and properties of the base class.
Problem is, once you've loaded the class, you can't officially unload it, and you do need to load it in order to extend it. So it's pretty tied up. Your best bet is to either hack the original class (not ideal) or copy paste the original class definition into a new file:
class ParentClass {
//Copy paste code and modify as you need to.
}
Somewhere after the bootstrapping of your framework:
spl_autoload_register(function ($class) {
if ($class == "ParentClass") { //Namespace is also included in the class name so adjust accordingly
include 'path/to/modified/ParentClass.php';
}
},true,true);
This is done to ensure your own modified class will be loaded before the original one.
This is extremely hacky so first check if the framework you're using has native support for doing this.

php - class extending alternative

I have a main class that I add around a dozen child classes to similar to Example #2.
I'm wondering if there is a better way to accomplish this. I know I could do "extends" on classes (Example #1) however in order to be able to have one variable with access to all extended class functions, I'd have to "daisy chain" the extensions and then create a new class reference on the very last extension - this option is not what I'm looking for.
Example #1:
class main {
function _construct(){}
function main_function1(){}
function main_function2(){}
}
class child1 extends main{
function _construct(){}
function child_function1(){}
function child_function2(){}
}
class child2 extends child1 {
function _construct(){}
function child_function3(){}
function child_function4(){}
}
$main = new child2();
$main->child_function1();
$main->child_function2();
$main->child_function3();
$main->child_function4();
Here is what I'm currently doing.
Example #2:
<?php
class main {
function _construct(){}
function main_function1(){}
function main_function2(){}
}
class child1 {
function _construct($main){$this->main = $main;}
function child_function1(){}
function child_function2(){}
}
class child2 {
function _construct($main){$this->main = $main;}
function child_function3(){}
function child_function4(){}
}
$main = new main();
$main->child1 = new child1($main);
$main->child2 = new child2($main);
$main->child1->child_function1();
$main->child1->child_function2();
$main->child2->child_function3();
$main->child2->child_function4();
?>
Is Example #2 the best way to achieve what I'm looking for?
By doing
class child {
function __construct($main){$this->main = $main;}
}
in Example 2 you would pass the $main instance as a property for child in the constructor. In my opinion this would make sense, if $main is a container that provides information for child - which is useful if you would like to avoid having a constructor with many many arguments. According to your naming, it doesn't look like main is a container. Be aware, that you are creating a dependency between child and main then because if you want to instantiate child, you always need an instance of main in advance! What you are also doing in Example 2 is creating circular references:
$main = new main();
$main->child1 = new child1($main);
$main->child2 = new child2($main);
You would be able to call $main->child1->main then which means a high coupling between main and child. So I'd rather not say "go for Example 2".
In your case it rather sounds like child actually is a special case of main, like the relationship between fruit (main) and apple (child). That makes using extends much more reasonable. You seem to be unsure, because you have many child classes extending main. To me this sound just normal, if all the child classes have a similar purpose and share some basic functionalty which is provided by main. But I'm not quite sure what your goal actually is.
Extending classes can break encapsulation, so depending on your classes it might be best to keep your objects separated as in example #2. You could have a loading function to make setting up the main class easier:
class main {
function load($class){
$this->$class = new $class();
}
}
$main = new main();
$main->load('child1');
$main->child1->child_function1();
In php, You have two options. Either (in 2020) inject your Helper Class in another class as suggested in the first answer or in PHP you can use traits.
Traits are similar to classes but their constructors cannot be public.
It's difficult to use Dependency injection on traits but traits can extend existing classes with methods and they can access the parent methods of their respective classes.
With traits anyway you cannot override the parent methods, you can only add the methods to the stack.
Another downside of traits is that, when you use the parent methods of the containing class, type hinting is not well supported in some IDEs. So in order to get type hinting working you'll need some workarounds.

multiple ways of calling parent method in php

At first I was confused why both of the method calls in the constructor work, but now I think I understand. The extending classes inherit the parent's methods as if they were declared in the class itself, AND the methods exist in the parent, so both should work.
Now I'm wondering if there is a preferred way (i.e. best practice) of calling the method (via parent or this), and whether or not these are truly identical ways of executing the same code, or if there are any caveats when using one over the other.
Sorry, I'm probably over thinking this.
abstract class Animal {
function get_species() {
echo "test";
}
}
class Dog extends Animal {
function __construct(){
$this->get_species();
parent::get_species();
}
}
$spike = new Dog;
There are three scenarios (that I can think of) where you would call a method in a subclass where the method exists in the parent class:
Method is not overwritten by subclass, only exists in parent.
This is the same as your example, and generally it's better to use $this->get_species(); You are right that in this case the two are effectively the same, but the method has been inherited by the subclass, so there is no reason to differentiate. By using $this you stay consistent between inherited methods and locally declared methods.
Method is overwritten by the subclass and has totally unique logic from the parent.
In this case, you would obviously want to use $this->get_species(); because you don't want the parent's version of the method executed. Again, by consistently using $this, you don't need to worry about the distinction between this case and the first.
Method extends parent class, adding on to what the parent method achieves.
In this case, you still want to use $this->get_species(); when calling the method from other methods of the subclass. The one place you will call the parent method would be from the method that is overwriting the parent method. Example:
abstract class Animal {
function get_species() {
echo "I am an animal.";
}
}
class Dog extends Animal {
function __construct(){
$this->get_species();
}
function get_species(){
parent::get_species();
echo "More specifically, I am a dog.";
}
}
The only scenario I can imagine where you would need to call the parent method directly outside of the overriding method would be if they did two different things and you knew you needed the parent's version of the method, not the local. This shouldn't be the case, but if it did present itself, the clean way to approach this would be to create a new method with a name like get_parentSpecies() where all it does is call the parent method:
function get_parentSpecies(){
parent::get_species();
}
Again, this keeps everything nice and consistent, allowing for changes/modifications to the local method rather than relying on the parent method.
Unless I am misunderstanding the question, I would almost always use $this->get_species because the subclass (in this case dog) could overwrite that method since it does extend it. If the class dog doesn't redefine the method then both ways are functionally equivalent but if at some point in the future you decide you want the get_species method in dog should print "dog" then you would have to go back through all the code and change it.
When you use $this it is actually part of the object which you created and so will always be the most up-to-date as well (if the property being used has changed somehow in the lifetime of the object) whereas using the parent class is calling the static class method.

Understanding Classes in PHP

I'm officially mentally retarded. [Let me explain]
I've never really given classes and their relationship any thought until today. I'm trying to figure out something that seems to be pretty obvious but since I'm stupid I can't see it.
Let's say I have a Core Class that will be extended from different files. How can children classes call functions from other siblings (that is if those are considered childs at all).
Sample Code: (don't kill me)
class cOne {
public function functionOne(){
echo "something";
}
}
Then on another file, I say:
class cOneChildOne extends cOne {
public function functionOne(){
echo "something from child one";
}
}
And yet on another file I say:
class cOneChildTwo extends cOne {
public function functionOne(){
echo "something from child two";
}
}
How would I have to create a new object, and when, so that I'm able to access functions from both childs and the parent class in a fashion similar to $newObject->Children->function(); I'm seriously considering the option that I've completely lost my brain today and can't think straight.
I've obviously doing something wrong since: $newObject = new cOne; creates the object but then the code from one of the subclasses is unable to access anything that's not directly in the core class or in itself.
Thanks
You can collect child instances in masters class static array
class C1{
static public $childs=array();
function __construct(){
self::$childs[]=$this;
}
}
class C1C1 extends C1{
function hi(){
echo 'hi from C1C1 <br />';
}
}
class C1C2 extends C1{
function hi(){
echo 'hi from C1C2 <br />';
}
}
$c1 = new C1C2();
$c2 = new C1C2();
$c3 = new C1C1();
$c4 = new C1C1();
$c5 = new C1C1();
$c6 = new C1C1();
foreach(C1::$childs as $c){
$c->hi();
}
The parent class cOne has no knowledge of the classes that extend it in php, so while you can call to the parent from a child class using parent::someFunction(), you cannot call the child classes from the parent. You also could not call functions from other classes that extend cOne from a class that extends cOne, also because cOne has no knowledge of classes that extend it.
You do have a fundamental misunderstanding.
Your two subclasses are different classes with a common ancestor. Each child essentially has knowledge of the parent, but the parent has no knowledge of the children, and the children have no knowledge of each other.
If you want child1 to be able to call methods of child2, then there is something wrong with your design. One solution would be to move the method from child2 to the parent class, so that child1 would also inherit that method.
you can use parent::functionOne(); to call functions of parent class from child class.
you can't call child classes' functions from parent class.
Help me or shoot me!!
Bang!!! =o)=o)=o)
When you create instance of class it only knows its methods and methods from its parents.
There is no way you can tell that there are other class who are extending same parent.
As kgb says, you can't create one object that will give you "access" to both sibling class' behaviour. If you instantiate a cOneChildOne, you'll get something that outputs "something from child one" (*). You could, if you use parent::functionOne(), copy cOne's behaviour, maybe to return "something\nsomething from child one" or whatever.
(*) Don't do this. Rather, return a string:
public function functionOne(){
return "something from child one";
}
This lets you compose your functions, output them to files, etc.
You could always just call cOneChildTwo from inside cOneChildOne statically if this suffices your requirement. $this in a method always points to the callee object (that's how parent::__construct() works), so you could use the callee's state inside cOneChildTwo for extended behaviour.
However, this would possibly imply that you'd require wrapper methods for every sibling's method. This is nothing Reflection can't solve though.
i think you're looking at object inheritance, classes and their relationships the wrong way.. what you've said is not really how inheritance in object oriented programming works. when you want to call a method/function of some other object, may it be an instance of the same class or not, what you need is a reference to that object that you are going to call. the keyword here is pass a reference. the one wanting to call must have a reference to the object it wants to communicate to.
child1.communicateWithAnotherChild(someOtherChild)
Why can't you have a static Array $children in the cOne class, and the __construct() methods for the classes that extend it just call cOne::addChild($this)? They could each implement a getChildren function which sends the request on to the superclass - Shouldn't that work?

Categories