PHP parent and using it in code not in the class itself? - php

I have 2 classes like
class A {
public function B () {
return 'b';
}
}
class C extends A {
public function D () {
return 'd';
}
}
I know that to use function b in class C I do,
class A {
public function B () {
return 'b';
}
}
class C extends A {
public function D () {
$b = parent::B();
return 'd';
}
}
But what about when I initiate the object? Do I have to do (which works)
$c = new C();
$b = $c -> b();
Or do I still have to use this parent keyword?
I tried doing,
$c = new C();
$b = $c -> parent::B();
But it does not work.
Thanks

You do not need the parent keyword in the second example, since class C extends A, it inherits all of its member functions and variables. So, $c->b(); is perfectly valid. Here is a link to the documentation on the extends keyword, which states:
Often you need classes with similar variables and functions to another
existing class. In fact, it is good practice to define a generic class
which can be used in all your projects and adapt this class for the
needs of each of your specific projects. To facilitate this, classes
can be extensions of other classes. The extended or derived class has
all variables and functions of the base class (this is called
'inheritance' despite the fact that nobody died) and what you add in
the extended definition.

When class C extends from A, you can use this to reach function B():
class C extends A {
public function D () {
$b = $this->B();
return 'd';
}
}
And likewise, from an instantiated class C you should call it as you mentioned using $c->B(). The parent:: construct is only meant to be used inside class methods; it can't be used outside of the class declaration.

Use the one that works.
When an instance inherits functions they are directly callable from that object. The caller does not need to be aware of whether b is some function of C or if c inherited it from another class.

Related

PHP - Call a method from the class where i instantiated my object

I have 2 classes declared like in the example below.
class A{
protected $process;
public function __construct() {
......
$this->process=new B();
}
public function do_something(){
....
}
}
class B{
// content not important
// I need to call do_something from class A
}
My question is, how can I call from class B the method do_something() from class A? Is it possible?
From your example it is impossible for instance of B to know that it is instantiated and stored by an instance of class A. You need to create that connection explicitly in some way.
I didn't think this would even work, but apparently you can pass instance of A to B before A is even done with its constructor:
class A {
protected $process;
public function __construct() {
$this->process = new B( $this );
}
public function do_something() {
var_dump( 'do_something' );
}
public function test() {
$this->process->test();
}
}
class B {
public function __construct( A $a ) {
$this->a = $a;
}
public function test() {
$this->a->do_something();
}
}
$a = new A();
$a->test(); // do_something
It's hard to give an advice on what the best approach for your particular case would be, as we don't know what either A or B does.
There's a few ways to achieve this. One way would be to make B and extension of A - thereby allowing all methods of the class A to be callable on the object B. Another way is to create a new object of A inside B and call that method. Or you can pass
Here's an example where B is extended from A. By doing this, all properties and methods of A can be called on B, unless overwritten in B.
class A {
public function doSomething(){
echo "doSomething() called in A";
}
}
class B extends A {
public function someMethod() {
$this->doSomething();
}
}
$b = new B();
$b->someMethod();
The above would output doSomething() called in A.
Or, you can create an object A and call that method inside B.
class B {
public function someMethod() {
$a = new A();
$a->do_something();
}
}
$b = new B();
$b->someMethod();
After reading all the answers and doing some research i think that the best method for me was the use of Traits
"Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies."
So i declared a Trait with the method do_something and call that method from Both class A and Class B
Thanks

Can I extend IDEs suggestions by creating class collisions

If a library I use, have a class that extends 2 other classes by the use of __call(), only the main extended class gets it's methods listed in the objects suggestions.
I noticed that if I make another php file in the project, where I put a class with the same name and namespace, and let it extend the other class, the IDE don't know witch one of them I'm referring to and gives me the suggestions for both of them, that way it suggests the methods from both of the extended classes.
This works sometimes, but in some case the IDE is to smart, and somehow know that my class isn't the real one, and only shows methods from the main extendsion.
Is there a better way to tell the IDE that a class in the library have more functions that it seams? Or a way that at least works every time?
Example:
<?php // index.php
include(__DIR__ . "/lib.php");
$c = new c();
echo $c->s_a();
echo $c->s_b(); // Accepted by the IDE
$d = new d();
echo $d->s_a();
echo $d->s_b(); // Not acceted by the IDE
<?php // lib.php
class a {
function s_a() { return "a";}
}
class b {
function s_b() { return "b";}
}
class c extends a {
public $b;
function __construct() {
$this->b = new b();
}
function __call($name, $arguments) {
return call_user_func_array(array($this->b, $name), $arguments);
}
}
class d extends c {}
<?php // fake.php
class c extends b {};
For $c the IDE don't know if it should use class c from lib.php or from fake.php, so it gives be a list with the methods of both.
For $d the that is of class d that extends c, it somehow know that its class c in file lib.php, so $d->s_b() are not sugested.

PHP OOP extend class or pass it as parameter

i am confused a little, well for a long time, i've used PHP classess in this way:
class A {
private $temp;
public function __construct() {
for($i=0; $i<=300000; $i++) { $this->temp[ $i ] = "Nedzad Alibasic"; }
}
}
and then another class which contains parameter in construct where i would pass class A as declared model:
class B {
private $a;
public function __construct($a) { $this->a = $a; }
}
And everything was fine, i could easy refer to class A by $b->a->somefunction(); but always it seemed to me, when i allocate A class to B, i would charge extra memory, because i passed the whole class? But how do i see it, there's almost no difference between passing and extending class?
I mean, is there someone who can lead me why should i switch from this way to class B extends A { /** code **/ } when there's almost no difference in memory?
Or there's something else usefull i could use with extends, but can't use within passing class as parameter.
Best regards.
The advantage of extending instead of wrapping inside an attribute of the class is that, when you extend, you are saying that B is also of type A, which means that everywhere in your code where needs an A class, B could be used if B extends from A.
<?php
class A {
private $temp;
public function __construct() {
for($i=0; $i<=300000; $i++) { $this->temp[ $i ] = "Nedzad Alibasic"; }
}
public function getTemp(){
return $this->temp;
}
}
class B extends A{
public function __construct() {
parent::__construct();
}
}
function showFirstElementOfTemp($object){
if($object instanceof A){
echo $object->getTemp()[0];
}else{
echo "Not an A";
}
}
$b = new B();
showFirstElementOfTemp($b); //Outputs "Nedzad Alibasic"
As you can see, this works, because B is an A, and passing B as a parameter in a function where we check the instance and ensure we have a type of A, B is also accepted.
Other than that, wrapping an A for having access to it's methods and attributes is the same, except that you won't get this hierarchy of types that you have with inheritance.
What you're used to doing is a form of composition, whereas using extend is, of course, inheritance. Generally composition is to be preferred over inheritance. You should probably continue doing. There are loads of resources describing the pros and cons of composition versus inheritance; picking a good one is tricky but I recommend you read a few of them.

php class extends overwrite propetry and method

Consider the following example. class b is extending class a.
1) When class b extends class a, will it overwrite property a value?
2) When class b extends class a, will it overwrite method say?
class a {
public $a = 5;
function say() {
echo "Hi";
}
}
class b extends a {
public $a = 6;
function say() {
echo "Hi";
}
}
Yes, and Yes.
After extending a class you are able to change the default value.
See PHP: Visibility for more info.
Yes to both. In the property case it will override the default value of it.
Yes to everything.
Object oriented programming has inheritance and if the child redeclares/redefines methods or properties the parent ones will be changed. Child classes are usually used to provide more specific functionality whereas parent classes are used for general functionality.
If you wish to keep the parent ones the following would work.
class A {
public $a = 5;
function say() {
echo 'Hi';
}
}
class C extends A {
/* specific functionality here */
}
The pertinent and official documentation of this is here: http://php.net/manual/en/language.oop5.inheritance.php

PHP faked multiple inheritance - having object attributes set in fake parent class available in extended class

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.

Categories