Why does the code below:
class A {
public function foo() {}
}
class B extends A {
private function foo() {}
}
generates an fatal error while this:
class A {
private function foo() {}
}
class B extends A {
public function foo() {}
}
doesn't although the documentation says "If the child doesn't see the parent's private methods, the child can't override them"?
So let's analyze what you have:
class A {
private function foo() {}
}
class B extends A {
public function foo() {}
}
Here class A has a private method, and since it's private it's not seen in class B. So in class B you can create method with the same name. It's not overriding, it's just creating method with the same name.
And in this example:
class A {
public function foo() {}
}
class B extends A {
private function foo() {}
}
Method A::foo is public and you can override it in class B. But as it's public, visibility of children method shouldn't be stricter then parent one. So you can't have B::foo as private, only public.
It is all about semantic. In first example in method foo of class B you can call parent method foo of class A using parent::foo(), but he is a private.
Related
I learned that I can use a parent's constructor in PHP with ParentClass::__construct();.
I imagine it's not possible, but I want to be sure; can I override or remove an aspect of the copied constructor? In other words, if the parent's constructor was
public function __construct(){
print "This is from the parent class";
test();
}
public function test(){
print "Remove this function when copying to child class";
}
is there any way that I can
public function __construct(){
ParentClass::__construct();
//override/remove/negate test() function in the copied construct.
}
Right now, your object structure is like this:
class ParentClass {
public function test(): void {}
}
class ChildClass extends ParentClass {
// This class has access to test() through inheritance
}
What you could have instead:
class BaseClass {
// Here, have everything that's actually common between all subclasses
}
class ClassA extends BaseClass {
public function test(): void {}
}
class ClassB extends BaseClass {
// This class does not have access to test()
}
You could also mix in some interfaces, but that's the basic idea.
Can It be possible to have a private concrete method inside the abstract class in Php
TL;DR: yes, you can.
abstract class Foo
{
private function test() {
echo 'abstract private' . PHP_EOL;
}
public function useTest() {
$this->test();
}
}
class Bar extends Foo {}
$x = new Bar;
$x->useTest();
Live example: https://3v4l.org/Efd5Q
But that private method will be visible ONLY to that abstract class. It means, that it will have to be used by some other concrete method within the abstract class (with protected of public visibility).
The child classes won't be able to call it directly.
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.
How can I prevent the something method below to be created in the foo class ?
class fooBase{
public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
Use the final keyword (like in Java etc):
class fooBase{
final public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
See PHP Final keyword. Note that foo will still have a method something, but something will only come from fooBase and foo can't override it.
Use the final keyword.
In your parent:
final public function something()
You can use final to prevent base methods being overwritten.
class fooBase{
final public function something(){
}
}
I have used faking of multiple inheritance as given in Can I extend a class using more than 1 class in PHP?
Notice that class A actually extends class B and faking is done for extending from class C.
It was working fine until I needed an attribute set in a function of class C to be available in class A. Consider a little edited version of that code where I call a function of class C from inside a function of class A :-
//Class A
class A extends B
{
private $c;
public function __construct()
{
$this->c = new C;
}
// fake "extends C" using magic function
public function __call($method, $args)
{
return call_user_func_array(array($this->c, $method), $args);
}
//calling a function of class C from inside a function of class A
public function method_from_a($s) {
$this->method_from_c($s);
echo $this->param; //Does not work
}
//calling a function of class B from inside a function of class A
public function another_method_from_a($s) {
$this->method_from_b($s);
echo $this->another_param; //Works
}
}
//Class C
class C {
public function method_from_c($s) {
$this->param = "test";
}
}
//Class B
class B {
public function method_from_b($s) {
$this->another_param = "test";
}
}
$a = new A;
$a->method_from_a("def");
$a->another_method_from_a("def");
So, an attribute set in a function of class C is not available afterwards in class A but if set in class B, it is available in class A. What adjustment am I missing so as to make setting of attributes in the fake parent class work like real? An attribute set in fake parent's function should be available in all the classes of the hierarchy like in normal case.
Thanks
Solved
I added the magic function __get() in class A and it worked.
public function __get($name)
{
return $this->c->$name;
}
That will never work, because 'param' is not a property of A: it is in c, which is a property of A.
What you need to do is define the magic methods such as __set and __get, which parallel __call for properties.