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
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.
My Class is independant from another Class.
Inside my Class, a function is doing the same but refined job as a function in another Class. Can I use parent:: function_in_another_class() and get my function join that parent funciton's job flow?
No.
In PHP you can only extend from none or one class. As you write both classes are independent to each other, there is no information where to find the one or the other class.
But what you're looking for is probably this:
class A
{
function myFunction() {}
}
class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
public function myFunction()
{
$this->a->myFunction();
}
}
If any class method already doing the same thing why would you bother call join it?
You can not do it. If you want the same job flow best way to do is to instantiate the other class and invoke that very same method. Thats why we use OOP.
See the example,
interface Fable()
{
public function f();
}
class OtherClass implements Fable
{
public function f()
{
// job flow
}
}
class MyClass
{
private $fable;
public function __construct(Fable $f)
{
$this->fable = $f;
}
public function method1($args){
return $this->fable->f($args);
}
}
If the current class is a child of another class, yes, you can. parent references to the parent class.
From php.net:
<?php
class A {
function example() {
echo "I am A::example() and provide basic functionality.<br />\n";
}
}
class B extends A {
function example() {
echo "I am B::example() and provide additional functionality.<br />\n";
parent::example();
}
}
$b = new B;
// This will call B::example(), which will in turn call A::example().
$b->example();
?>
The best you can do here is to extend Class B from Class A
Class B extends Class A
But, you can also:
class ClassA {
function do_something($args) {
// Do something
}
}
class ClassB {
function do_something_inclassA($args) {
classA::do_something($args);
}
}
Important: calling classa::do_something(); is a static call, in other words with error reporting E_STRICT you will get a static notice warning because function do_something() is not static function do_something()
Also, calling this function statically (i.e. classa::do_something()) means that class a's function cannot refer to $this within it
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.
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.
<?php
class A{
//many properties
protected $myProperty1;
protected $myProperty2;
protected $myProperty3;
public function __construct(){
$this->myProperty1='some value';
$this->myProperty2='some value';
$this->myProperty3='some value';
}
public function getProperty1(){
return $this->myProperty1;
}
public function getProperty2(){
return $this->myProperty2;
}
public function getProperty3(){
return $this->myProperty3;
}
//edited: I added some setters, meaning that the object returned from the functions may already have these properties altered
public function setProperty1($p){
$this->myProperty1=$p;
}
public function setProperty2($p){
$this->myProperty2=$p;
}
public function setProperty3($p){
$this->myProperty3=$p;
}
}
class B extends A{
private $myProperty4;
public function __construct(A $a){
$this=$a; //this line has error,it says $this cannot be re-assigned
$this->myProperty4='some value';
}
public function getProperty4(){
return $this->myProperty4;
}
}
//$a = new A();
$a = someClass::getAById(1234); //edited: $a is returned by a function (I cannot modify it)
$b= new B($a); //error
?>
I'd like to create a B's object by passing an A's object to B's constructor, as you can see, I cannot re-assign the $this variable. I am not allowed to modify class A, when there are many properties in A, it'd be tedious for me to do things like this in B's constructor:
public function __construct(A $a){
parent::__construct();
$this->myProperty1=$a->getProperty1();
$this->myProperty2=$a->getProperty2();
$this->myProperty3=$a->getProperty3();
$this->myProperty4='some value';
}
My question is that, how can I safely create an object of class B using an A's object with minimal amount of coding?
class A
{
public $property = 'Foobar';
}
class B extends A
{
public function __construct()
{
echo $this->property; // Foobar
}
}
Am I missing something? It sounds like you're trying to force OOP to do something it's not intended to do, or you're having trouble understanding inheritance.
Every public or protected method and property from class A is available in class B. Either by directly referencing it (as in my example) or by using the parent:: syntax.
EDIT
(Author clarified question)
If class A's properties are accessible, you could use something like the following to copy them down to class B
class B
{
public function __construct()
{
$a = new A(); // Or however A is instantiated
foreach(get_object_vars($a) as $key => $value)
{
$this->$key = $value;
}
}
}
Since B extends A, why not just create B to begin with? If you need to initialize some extra properties, you can over-ride the constructor like this:
class B extends A {
public function __construct(){
parent::__construct(); //calls A's constructor
$this->Bproperty='somevalue';
}
}
If that's not good enough, then you might want to look at Reflection.