This question already has answers here:
PHP: differences in calling a method from a child class through parent::method() vs $this->method()
(2 answers)
Closed 9 years ago.
How is it possible to call a overwritten parent function recursively from a child instance? Since I'm not using static methods I can't use parent::method() but have to do somehow different. I have a feeling that there is a better approach to my problem, maybe through a design pattern. This is my class structure:
class Creature {
public function eat() {
// feed and digest
}
}
class Mammal extends Creature {
public function eat() {
// gather and chew
}
}
class Human extends Mammal {
public function eat() {
// have a meal
}
}
class WesternPerson extends Human {
public function eat() {
// use knife & fork
}
}
$me = new WesternPerson();
$me->eat();
Calling eat() shall go recursively upwards from the special to the very abstract class. Most simple way would be if I could call the parent function with the same name from within the overwritten one. But I know, it's overwritten, so I can't.
The :: isn't just for static methods. It is the scope resolution operator. It is used any time you want to utilized a function that exists in scope other then your contextual scope.
parent, static, and self are language constructs that reference different scopes that relate to your calling scope.
So in this case
parent::eat()
will call the Human::eat in the WesternPerson::eat context (ie $this will mean the WesternPerson Instance in the Human::eat context)
As stated in comments, calling parent::eat() would work just fine
Related
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();
}
This question already has answers here:
PHPUnit - Use $this or self for static methods?
(3 answers)
When should I use 'self' over '$this'?
(23 answers)
Closed 3 years ago.
I was messing around and discovered that you could actually call static methods with $this->method()
And it got me a bit confused and curious about the differences between the 3 ways (that I know of) to call static methods
$this->method();
static::method();
self::method();
Now, I think I understand the difference between the latter two, but what about the first one?
It is important to understand the behavior of static properties in the context of class inheritance:
Static properties defined in both parent and child classes will hold DISTINCT values for each class. Proper use of self:: vs. static:: are crucial inside of child methods to reference the intended static property.
Static properties defined ONLY in the parent class will share a COMMON value.
declare(strict_types=1);
class staticparent {
static $parent_only;
static $both_distinct;
function __construct() {
static::$parent_only = 'fromparent';
static::$both_distinct = 'fromparent';
}
}
class staticchild extends staticparent {
static $child_only;
static $both_distinct;
function __construct() {
static::$parent_only = 'fromchild';
static::$both_distinct = 'fromchild';
static::$child_only = 'fromchild';
}
}
$a = new staticparent;
$a = new staticchild;
More on https://www.php.net/manual/en/language.oop5.static.php
self using for static method and variable in class
$this using for non static method and variable
static generally using call child class of static methods or variable
For example late static
For example late static binding
This question already has answers here:
Is subclass inherits private members from parent class? [duplicate]
(2 answers)
Closed 5 years ago.
Accept my apologies for being beginner for OOP,
according to the below code :
Class Test{
private $name = "youhana";
function setPrivatePropFromInside(){
$this->name = "mina";
}
function getPrivate(){
var_dump(__CLASS__);
echo $this->name ;
}
}
Class Test2 extends Test {
}
$obj2 = new Test2();
$obj2->getPrivate();
My Question is that Is Inheritance means to copy from parent to child or the child gain access to the parent visible members?
let me describe why I have confusion by mentioning my thoughts with both of the question members :
In case its a copy, so the invoking the method getPrivate from the child object must return null because the private members will not be copied from the parent to the child, and also the CLASS constant must return Test2 not TEST in case the Inheritance means copying.
so the code mentioned above would equals :
Class Test{
private $name = "youhana";
function getPrivate(){
var_dump(__CLASS__);
echo $this->name ;
}
}
Class Test2 extends Test {
function getPrivate(){
var_dump(__CLASS__);
echo $this->name ;
}
}
In case Inheritance means to gain access to the parent visible members, that doesn't refer or point to the concept of inheritance (the children get the characteristics of the parent) despite this concept is logically correct with the results upon executing the mentioned code snippet.
I Read more than 20 References and I still have the confusion, and again accept my apologies for being beginner searching for the correct approach.
Note that: I asked a question Here but after studying more references, I have been returned back to the confusion again, so I need a solid answer.
It's nothing to do with "copying".... a class defines methods and properties together with a visibility indicating from where those methods and properties can be accessed.
When one class extends another, then you are creating an inheritence hierarchy or tree, or a set of class contexts.
When you instantiate a child class, you are actually instantiating an object that inherits that full tree.
When you call a method against that instance, it looks to see if that method exists (and is accessible) in the child class definition. If so, it executes it in that context: if not, it looks to see if the method exists in the parent class; and if so, will execute it in that context.
When a method executes in a specific context within the hierarchy of class extensions, it has access to everything visible in that context. Private properties are only accessible in the context where they are defined/the class where they are defined; but methods in that context/class have access to those private properties.
If (as in this case) your public getters and setters exist in the same class/context as the private property, then those methods have access to the private property (because they are in the same class/context), and can be used to access it from outside of that context because the getters/setters themselves are public.
Is Inheritance means copy from parent to child or the child gain
access to the parent visible members?
The child gain access to the visible members of parent class. Also, you get flexibility to override the feature (method) of parent class.
I think your confusion comes from thinking that
private $name = "youhana";
is a static value which exists in class declaration. In any case, that is just a shorthand for declaring variable values in constructor so even if inheritance "copy" from parent its a wrong example to show that. What you should be asking is: do static properties get copied from the parent? Static properties exists in class declaration and any modifications are visible to all objects of that class.
php docs on static properties
Answer is no. Only reference to parent's value is passed.
I wrote a simple example to illustrate
<?php
class Foo
{
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
public function modifyFooStatic(){
return self::$my_static .= '+';
}
}
class Bar extends Foo
{
public function fooStatic() {
return self::$my_static;
}
public function modifyBarStatic(){
return self::$my_static .= '-';
}
}
$foo = new Foo();
$foo->modifyFooStatic();
print $foo->staticValue() . "\n"; // foo+
$bar = new Bar();
$bar->modifyBarStatic();
print $bar->fooStatic() . "\n"; // foo+-
?>
As you can see both child and parent modifies the same variable even if child calls it with sellf::$my_static
PHP 7 has introduced a new class feature called the anonymous class which will allow us to create objects without the need to name them. Anonymous classes can be nested. What are your thoughts on memory consumption, execution time, performance issues? Are there any metrics/stats available?
Anonymous classes are classes without programmer declared names, they are otherwise identical to normal classes.
Syntax allows them to be nested, just like functions:
function name() {
function sub() {
}
}
But just as the code above contains two globally accessible functions, the following code still contains two globally accessible classes:
class C {
function method () {
return new class{};
}
}
It gives you a kind of control over where the class is easily accessible from, in that sense they are nested.
They are not nested in the sense that an anonymous class declared inside another class is not able to access any members of the creating class.
So that this:
class C {
private $member;
public function method() {
return new class {
public function method() {
return $this->member;
}
};
}
}
Is not valid, because the anonymous class is not truly nested.
I recently began to develop in php5 in an object oriented way and I'm stuck at something. I would really appreciate your help/recommendations.
Bear with me in this since it ended up in a mess :-(
This is my scenario (hope I can elaborate on this clearly): I have two dynamic classes, Client and Supplier which use methods of a static class called Vocabulary. Vocabulary is a class that pulls vocabulary terms from a source which can be: plain text file, mongodb database or mysql database. An entry in a configuration file determines which of the
aforementioned three types of sources the application will use.
class Client {
public function foo() {
...
Vocabulary::getTerm();
...
}
...
}
class Supplier {
public function bar() {
...
Vocabulary::getTerm();
...
}
...
}
class Vocabulary {
public static function useVocab($vocab) {
$_SESSION['vocab'] = $vocab;
}
public static function getTerm($termKey) {...}
...
}
I planned to create Vocabulary child classes for each of the types I want to support, for example: Vocabulary_file, Vocabulary_mongodb and Vocabulary_mysql.
Vocabulary_file will override its parent useVocab() because it needs to perform additional operations appart from setting the $_SESSION variable, but
Vocabulary_mongodb and Vocabulary_mysql don't need to override their useVocab() parent method (they just need the $_SESSION variable set).
All three Vocabulary "child" classes will override getTerm() method.
The following is what I tried and this is the mess I ended up with :-(
For Vocabulary_mongodb and Vocabulary_mysql, since useVocab() doesn't exist but is inherited from Vocabulary, "method_exists()" returns true and that call
causes an infinite loop.
I looks weird both calling the child explicitly in Vocabulary and calling the parent:: in the child class.
After lots of cups of coffee I have exhausted all my wits and my brain is damaged.
// Class Vocabulary modified to make it call the desired "child" class too
class Vocabulary {
// This would execute "child" class method
private static function _callChild($method, $args) {
$child_class = 'Vocabulary_' . Config::$vocab['type']; // Config::$vocab['type'] can be: file, mongodb or mysql
if (method_exists($child_class, $method)) {
return call_user_func_array($child_class . '::' . $method, $args);
} else {
return false;
}
}
public static function useVocab($vocab) {
$_SESSION['vocab'] = $vocab;
self::_callChild(__FUNCTION__, compact('vocab'));
}
public static function getTerm($termKey) {
$termKey = strtolower($termKey);
self::_callChild(__FUNCTION__, compact('termKey'));
}
...
}
class Vocabulary_file extends Vocabulary {
public static function useVocab($vocab) {
parent::useVocab($vocab);
// some specific stuff here
}
public static function getTerm($termKey) {
parent::getTerm($termKey);
// some specific stuff here
}
}
class Vocabulary_mongodb extends Vocabulary {
public static function getTerm($termKey) {
parent::getTerm($termKey);
// some specific stuff here
}
}
class Vocabulary_mysql extends Vocabulary {
public static function getTerm($termKey) {
parent::getTerm($termKey);
// some specific stuff here
}
}
I would like to know how can I design the Vocabulary classes in order to keep the Vocabulary::... like calls in Client and Supplier and let Vocabulary know which child class use for the type configured in "Config" class.
Any advice will be greatly appreciated.
Cheers
If you're using all static methods, you may as well not use OOP at all, it's basically all just global function calls. If you want inheritance with polymorphism to work, you pretty much need to instantiate your classes. The polymorphism then comes from the fact that the instantiated objects can be anything, but you're calling the same methods on them. E.g.:
abstract class Vocabulary {
abstract public function getTerm($termKey);
}
class Vocabulary_File extends Vocabulary {
public function getTerm($termKey) {
// get from file
}
}
class Vocabulary_MySQL extends Vocabulary {
public function getTerm($termKey) {
// get from database
}
}
You can use this polymorphic like this:
if (mt_rand(0, 1)) {
$vocab = new Vocabulary_File;
} else {
$vocab = new Vocabulary_MySQL;
}
// This call is polymorphic.
// What exactly it does depends on which class was instantiated.
$vocab->getTerm('foo');
This is how polymorphism is really useful. The interface (getTerm($termKey)) is defined and unchanging between classes, but the specific implementation changes. If your code is hardcoding calls to Vocabulary::getTerm(), that's not polymorphism. With your structure you're also violating an important OO design rule: The parent does not know about its children, and it does not interact with its children. The children override functionality of the parent, not the other way around.
You also shouldn't use the $_SESSION as a form of global storage. Keep objects self contained.
The keyword self suffers from inability to handle 'late-static-binding'. Basically, in the parent class, self thinks it's the parent class when it's inside it's own static functions (since self is still evaluated at compile time for legacy reasons).
You need to use static instead of self in the parent class (assuming you have php 5.3 or higher).
BTW: the parent keyword functions as you'd expect as the parent has to be known at compile time anyhow.
Here's an example:
public static function getTerm($termKey) {
$termKey = strtolower($termKey);
static::_callChild(__FUNCTION__, compact('termKey'));
}
If you're using php 5.2 and earlier, you have to try a hack around, like require all child classes to have static functions that return their class name. I hope you're on php 5.3 or higher...