Take the following example:
class A implements Serializable {
serialize() {}
}
class B extends A {
serialize() {}
}
Class A is a persistant but minimal class used on every page. class B is temporary admin only (used on a settings screen) class which populates members by reading files.
I need to serialize the object and store in the database twice, once for regular pages, and the second (with a limited life) for the admin page.
$instance = new B(); // and populate
$data = serialize( $instance );
This will always call the over-ridden method. Is there any way I could cast $instance to type A so that I can call on class A's serialize method?
It's possible by creating a closure, Looks following snippet for demonstration
<?php
interface Greeting
{
public function hello();
}
class A implements Greeting
{
public function hello()
{
echo "Say hello from A\n";
}
}
class B extends A
{
public function hello()
{
echo "Say hello from B\n";
}
}
$b = new B();
$closure = function() {
return parent::hello();
};
$closure = $closure->bindTo($b, 'B');
$closure(); // Say hello from A
$b->hello(); // Say hello from B
The answer is no, you cannot. The children redeclare the parent functionality of the method and completely override it. For this, static methods would be required.
Related
I have class B. In this class I create object classB(). And I have a question how can I pass this new classB() to another class ?
class A
{
public classB $classB;
public function __construct()
{
$this->classB = new classB();
}
}
class C
{
public function example()
{
/// here I want to object new classB() created in class A
}
}
If I take your code, only slightly altered:
class A
{
public $b;
public function __construct()
{
$this->b = new B();
}
}
Then continue to create an object from that class:
$a = new A();
Then I can access the public property b, which is an object of class B, like so:
$accessB = $a->b;
Now if you want to use property b in another class you can do:
class C
{
public function example($anObject)
{
// here you can use $anObject
}
}
$c = new C();
$c->example($a->b);
That's all there is to it.
Please, next time you want to provide an example, make it meaningful. So instead of say "class A" call it, for instance, "class Car", and "class Wheel". Using meaningful class names, that clearly relate to each other, helps to understand what you're doing and helps to get away from abstract code.
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
I'm learning OOP PHP. I want to call a method from another class to a new class.
For just a example:
<?php
class Aclass {
function aMethod($input)
{
echo 'Hello a world ';
}
}
?>
And i want to call the method aMethod from the class 'Aclass' into the new class.
<?php
class Bclass {
//calling the method here?
}
?>
i tried extending , still not working for me.
Thanks.
In your class Bclass you should create some functions. In case below you are creating a new instance of Aclass and then using function aMethod.
Example
<?php
class Bclass {
public function __construct() {
$a = new Aclass();
$a->aMethod("some_text");
}
}
?>
Other way is extend Bclass. In this case your class Bclass extends everything what's in Aclass so you can use it just with $this.
Example
<?php
class Bclass extends Aclass {
public function __construct() {
$this->aMethod("some_text");
}
}
?>
Also your function aMethod in Aclass should have public or protected visibility. Public if you create an instance, protected if you extends. More informations can be found in manuals at the end.
Example
<?php
class Aclass {
public function aMethod($input) // protected if you will extend this class
{
echo 'Hello a world ';
}
}
?>
You can of course use both methods not only in __construct but also in other functions.
Manuals
PHP: Visibility
PHP: Constructors and Destructors
For this I'd use dependency injection. Which is just a fancy way of saying "sending an object of the A class when creating B".
In other words, something like this:
class typeA {
public function __construct () {};
public function test () {
return 'Test string';
}
}
class typeB {
protected $testObj;
public function __construct (typeA $testCase) {
$this->testObj = $testCase;
}
public function getTest () {
return $this->testObj->test ();
}
}
$a = new typeA ();
$b = new typeB ($a);
echo $b->getTest ();
Constructors are meant to be used to create an object that's ready to be used, which is why I've just stored the dependency inside the typeB object itself. Then, in the getTest() method I invoke the test() method of the object I'm depending upon, in order to get the needed data from it.
Doing it in this manner will allow you to write flexible OOP code, which can easily be expanded and extended as you require. Hiding the dependencies inside the constructors, by creating objects there, creates a hidden and hard dependency. Something which makes it a lot harder, if not down right impossible, to properly leverage the extensible nature of the class-based designs.
I want to redefine a method, and call my ancestor's version of it, not my parent's.
Here is a short example:
// This class is autogenerated and I am not supposed to modify it.
class myParent extends myGrandparent {
function doSomething() {
doA();
doB();
doC();
parent::doSomething();
}
}
// Here is my code
class myClass extends myParent {
function doSomething() {
// doA(); // I don't want to do A anymore.
// doB(); // Neither B.
doC(); // But I want to keep doing C.
parent::doSomething(); // OOPS!! This does A and B (and C again)!
}
}
How can I call myGrandparent's method directly, instead of myParent's?
I disagree with the "you cannot do this" argument - You can do this with Reflection.
Consider the following class structure:
class A {
function foo() {
echo 'A';
}
}
class B extends A {
function foo() {
parent::foo();
echo 'B';
}
}
class C extends B {
function foo() {
parent::foo();
echo 'C';
}
}
When initialized with this:
$o = new C;
$o->foo();
Will print (as expected, seen in this demo):
ABC
The challenge is to remove the B from the output, effectively only executing A's foo() and C's foo(). So, lets drop into Reflection and grab A's foo() method, and invoke that on C's object. Now consider this alternative definition for C:
class C extends B {
function foo() {
$ref = new ReflectionClass( $this);
$parent = $ref->getParentClass()->getParentClass();
$parent->getMethod( 'foo')->invoke( $this);
echo 'C';
}
}
Now, you'll only get as output (as seen in this demo):
AC
Whether or not this is a "good practice", is up to the OP. I think I've demonstrated that it is possible to "skip" the implementation of B's function and call the grandparent function from the grandchild class.
Not sure what the use cases are, but unless I misunderstand the question/issue (quite possible), you can totally call any arbitrary ancestor (public or protected) method, irrespective of how many times it's been overridden in between, and even the default value of any ancestor member attribute (public or protected), even if that's been overridden too. For example, with the class hierarchy:
Papa > Mama > Baby > Infant, where both the method sayWhat() & instance variable $el are overridden in each descendent class, you can call any ancestor sayWhat method from Infant, and access a different ancestor default attribute value:
class Papa {
protected $el = 'PapaEl';
protected function sayWhat($className = null) {
if (!$className) {
$className = get_class($this);
}
$classVars = get_class_vars($className);
$localEl = $classVars['el'];
echo "<h2>What is PAPA!. El: [$localEl]</h2>";
}
}
class Mama extends Papa {
protected $el = 'MamaEl';
protected function sayWhat() {
echo "<h2>What is MAMA! El: [$this->el]</h2>";
}
}
class Baby extends Mama {
protected $el = 'BabyEl';
protected function sayWhat() {
echo "<h2>What is Lil' Baby!! El: [$this->el]</h2>";
}
}
class Infant extends Baby {
protected $el = 'InfantEl';
protected function sayWhat($className) {
Papa::sayWhat($className);
}
public function mySayWhat($className) {
$this->sayWhat($className);
}
}
$i = new Infant();
$i->mySayWhat('Mama');
Output:
What is PAPA!. El: [MamaEl]
Not sure what value it has, but if someone has the requirement, it seems very doable...
You really can't. You would either need to extend from myGrandParent directly, or you would need to rework the logic in MyParent to provide "pass-through" access to the myGrandParents method. For example, you could make a method on myParent like this:
function doSomethingGrandparent() {
parent::doSomething();
}
and then change your doSomething method in myClass like this:
function doSomething() {
parent::doSomethingGrandparent();
}
The answer is no, you cannot. The children redeclare the parent functionality of the method and completely override it.
I think static methods would be required, since you can't chain the parent:: keyword to work back to a "grandparent" class, so, parent::parent::foo( ) doesn't work.
class A
{
public function foo()
{
}
}
class B
{
$a = new A;
public function go()
{
}
}
I want A object cannot be created directly.But only by class B.
How i can do this.
Why would you need that?
Remember - a class is a defacto factory for objects, and the object should do things, and it should do them with passed params and available instance variables which means you should pass everything the object needs to the constructor and you should not care about the fact that the object can be created by everybody.
Seriously.
Sounds like you want to extend an abstract class.
abstract class A {
protected function foo() {
echo "Hello world!";
}
}
class B extends A {
public function go() {
$this->foo();
}
}
$obj = new B;
$obj->foo(); // error - cannot call a protected method directly
$obj->go(); // echo's "Hello world!"
If you really want to do this, check factory design pattern. I think it will what you are asking for. There we will have a separate factory class for managing object creation.