I understand that I should make a method "protected" when I want it to be only available to all classes that extend the current class as well as the current class.
Okay, grandChildClass::method2() should be protected since grandchild is extended from child.
But what should it be if accessed from a parent class such as parentClass::method2()?
class parentClass
{
public function method1() {$this->method2();}
}
class childClass extends parentClass
{
protected function method2() {}
}
class grandChildClass extends childClass
{
public function method3() {$this->method2();}
}
If you try to
$p = new parentClass;
$p->method1();
You'd get a fatal error for undefined method.
Fatal error: Call to undefined method parentClass::method2() in ... on line ...
However, this will work fine:
$c = new childClass;
$c->method1();
$g = new grandChildClass;
$g->method1();
$g->method3();
All of these will call method2 as defined on childClass.
Related
I have a parent class I'll be calling 'ParentClass' and a child class (that extends from it) which I'll be calling 'ChildClass'.
ParentClass has protected properties $prop1 and $prop2 which I want ChildClass to access. But I'm getting NULL from them.
ParentClass has a __construct() method which sets the properties received through dependency injection.
ParentClass instantiates ChildClass from one of its methods.
ChildClass overwrites the parent constructor, but doesn't contain any code inside of its own __construct() method.
I have already tested the properties at the parent class with var_dump($this->prop1). It returns the value I'm expecting.
However, if I var_dump($this->prop1) from the child class, I get NULL.
class ParentClass {
protected $prop1;
protected $prop2;
public function __construct($prop1, $prop2) {
$this->prop1 = $prop1;
$this->prop2 = $prop2;
}
public function fakeMethod() {
$child = new ChildClass;
$child->anotherFakeMethod();
// logic
}
}
class ChildClass extends ParentClass {
public function __construct() {
// this overrides the parent constructor
}
public function anotherFakeMethod() {
$prop1 = $this->prop1;
$prop2 = $this->prop2;
var_dump($this->prop1);
// returns NULL
}
}
Why can't the child class access the parent class' properties if it extends from it?
They are accessible, but they will be null because they are not passed to the parent constructor from the child:
(new ChildClass(1,2))->anotherFakeMethod();
Sandbox
Output
NULL
Your classes produce the expected result of null in this case. Well it produces what I would expect it to based on how it's coded.
To fix it, you must pass that data back to the parent class through the child's constructor, or remove the child's constructor. Like this:
class ChildClass extends ParentClass {
public function __construct($prop1, $prop2) {
parent::__construct($prop1, $prop2);
}
....
}
After the above change:
(new ChildClass(1,2))->anotherFakeMethod();
Output
int(1)
Sandbox
Which is what I would expect from this line as it's basically the first argument used in the constructor:
var_dump($this->prop1);
You can also do it this way, if you know what they are in the child class:
public function __construct() {
parent::__construct(1, 2); //say I know what these are for this child
}
You could of course set them manually in the new constructor but that would be WET (write everything twice) or unnecessary duplication, in this case.
Cheers!
I'm trying to access an object of a class in another extended class.
class MainClass{
protected $theobject;
function __construct(){
$this->theobject = new AnotherClass();
}
}
class TheClass extends MainClass{
function AnotherFunction(){
$this->theobject->SomeFunction();
}
}
I'm getting an error on $this->theobject->AnotherFunction(). The error is "Call to a member function SomeFunction() on a non-object".
But this works fine:
class TheClass{
protected $theobject;
function SoemFunction(){
$this->theobject = new AnotherClass();
$this->theobject->SomeFunction();
}
}
Is it even legal to do this in PHP?
Pretty much all the code: http://3v4l.org/MaXe6
When i var_dump the $this->theobject in TheClass is comes back as NULL.
class TheClass extends MainClass{
function __construct(){
parent::__construct();
}
function SoemFunction(){
$this->theobject->SomeFunction();
}
}
Do the construct method when init the child class.
If I have an abstract class like this:
abstract class MyApp
{
public function init()
{
$this->stuff = $this->getStuff();
}
public function getStuff()
{
return new BlueStuff();
}
}
And then I have a class that extends from this abstract class like this:
class MyExtendedClass extends MyApp
{
public function init()
{
parent::init();
}
public function getStuff()
{
return new RedStuff();
}
}
If I do:
$myobj = new MyExtendedClass();
$myobj->init();
Why does the method getStuff from the child class get called? Isn't $this in the context of the abstract class? If so, shouldn't the method of the abstract class get called?
Thanks!
New answer
In PHP you can use subclasses as if all methods in the parent class that don't exist in the subclass have been copied to the subclass. So your example would be the same as:
class MyExtendedClass extends MyApp {
public function init() {
$this->stuff = $this->getStuff();
}
public function getStuff() {
return new RedStuff();
}
}
Just think of the subclass as having all code of the parent class and you're normally all right. There is one exception to this rule: properties. A private property of a class can only be accessed by that class, subclasses can't access the private properties of parent classes. In order to do that you need to change the private property into a protected property.
Original answer
Abstract classes in PHP are just like regular classes with one big difference: they can't get initiated. This means you can't do new AbstractClass();.
Since they work exactly like regular classes for everything else, this also is the case for extending classes. This means that PHP first tries to find the method in the initiated class, and only looks in the abstract classes if it doesn't exist.
So in your example this would mean that the getStuff() method from MyExtendedClass is called. Furthermore, this means you can leave out the init() method in MyExtendedClass.
I mean something like that:
class parentClass {
public function method() {
echo $this->prop;
}
}
class childClass extends parentClass {
public $prop = 5;
}
How can I get a child prop from the parent prop?
Thanks...
Either I don't fully understand what you want or the solution is as trivial as the following code.
class parentClass {
public function method() {
echo $this->prop;
}
}
class childClass extends parentClass {
public $prop = 5;
}
$object = new childClass();
$object->method();
I mean the child class is extending the base class which means it will also inherit all the methods of its parent's class. That makes the whole process of using the parent's class method as simple as calling it from the instance of the child class.
All protected and public members of child classes are visible from within their parent class in PHP, so the example code you provided should work just fine. Quote from the php doc:
Members declared protected can be accessed only within the class
itself and by inherited and parent classes.
But the actual question is: do you really need it?
The proper OO way would be to define a self-contained parent class that expresses something. It should not need to access properties of child classes - this is a so-called code smell. If you really think that you have a case where a similar construct is necessary, you are probably looking for abstract methods, which guarantee that every child class has this property:
abstract class Animal {
public function makeNoise() {
echo $this->getNoiseString();
}
protected abstract function getNoiseString();
}
class Cat extends Animal {
protected function getNoiseString() {
return 'meow';
}
}
//parent
class parentClass {
protected $prop = null;
public function method() {
echo $this->prop;
}
}
//child
class childClass extends parentClass {
protected $prop = 5;
}
Make sure the variable is defined in the parentclass as well. So it will be accessible by the parent.
This thing has been bugging me for long and I can't find it anywhere!
What is the difference when using classes in php between :: and ->
Let me give an example.
Imagine a class named MyClass and in this class there is a function myFunction
What is the difference between using:
MyClass myclass = new MyClass
myclass::myFunction();
or
MyClass myclass = new MyClass
myclass->myFunction();
Thank you
MyClass::myFunction(); // static method call
$myclass->myFunction(); // instance method call
"::" is for calling static methods on the class. So, you can use:
MyClass::myStaticFunction()
but not:
MyClass->myStaticFunction()
as stated, "::" is for static method calls whereas "->" is for instance method calls
except for when using parent:: to access functions in a base class, where "parent::" can be used for both static and non-static parent methods
abstract class myParentClass
{
public function foo()
{
echo "parent class";
}
}
class myChildClass extends myParentClass
{
public function bar()
{
echo "child class";
parent::foo();
}
}
$obj = new myChildClass();
$obj->bar();
class MyClass {
static function myStaticFunction(...){
...
}
}
//$myObject=new MyClass(); it isn't necessary. It's true??
MyClass::myStaticFunction();