How to use an object to add to an attribute?

6

When I do the code below you get this error:

  

Object of class Client could not be converted to string in ... \ animal.class.php

This part does not allow me to pass an object to be used in the "owner" property

$dog = new Cachorro('Rex',$ana);

But when I use string 'ana' eg.:

$dog = new Cachorro('Rex','ana');

It works normally and returns me the "ana" as owner of the animal

//classe Cliente
class Cliente{
    public $nome;

public function __construct($nome){
        $this->nome     = $nome;
    }
}

abstract Animal{
    protected $nome;
    protected $dono;

   public function __construct($nome,$dono){
       $this->nome      = $nome;
       $this->dono  = $dono;
   }

  public function getDono(){
        return $this->dono ;
    }
}
//Essa classe foi implementada, porém nada está afetando e a deixei "isolei" para ter   certeza
class Cachorro extends Animal{

}

$ana = new Cliente('ana');
$dog = new Cachorro('Rex','ana' );
echo "Dono: ". $dog->getDono();
    
asked by anonymous 29.12.2014 / 05:18

3 answers

7

I will respond as you have divergent answers and do not know what to do.

You have already learned from the other answers that there is a type compatibility problem. Under normal conditions you can not print the content of a complex type, in general that you have created. no component knows how to print this dataset. You, the creator of the type need to "teach" the application how to do this. You're always worried about doing the right thing and that's for sure. Every class should take responsibility for everything that concerns it.

So creating the __tostring() method, as defined by the sergiopereira response, is not only useful, it is almost mandatory. In fact, some programming languages do. Or at least they provide a standard method for doing this for all classes (how to do this varies depending on the language philosophy).

In fact Guilherme Nascimento is right to call this method of magic but has no problem using it. The builder is also magical. There is no and should not even rule to prevent its use. On the contrary, these are desirable methods in certain situations.

You like to do the right thing. So, when you build an instance of Cachorro do you mean that it is associated with a owner or a owner name ? It seems that his initial intention was to use the first form. And I think it's better. It's not wrong to just put a pet's name on the dog if you wish but I think dogs have owners altogether. How to pass the name you only have the name, does not really associate with the owner. In most situations it is not what you need. I would discard any solution on top of the name.

Then your initial solution was correct. The mistake was in accessing the owner. You tried to print the owner and the application did not know how.

If your intention was to explicitly print the owner's name, then you should ask to print the owner's name and not to print the owner. It may seem silly but conceptualizing things correctly in programming is critical. If you do not define precisely what you want to do, you will not be able to express it correctly.

So the two answers are correct, they just did not explain to you when and why to use each one. I would use both.

<?php

class Cliente {
    private $nome;

    public function __construct($nome) {
        $this->nome = $nome;
    }

    public function getNome(){
        return $this->nome;
    }

    public function __toString() {
        return $this->nome;
    }
}

abstract class Animal {
    protected $nome;
    protected $dono;

    public function __construct($nome, $dono) {
       $this->nome = $nome;
       $this->dono = $dono;
   }

    public function getDono() {
        return $this->dono;
    }
}

class Cachorro extends Animal {

    public function __construct($nome, $dono) {
       parent::__construct($nome, $dono);
   }
}

$ana = new Cliente('ana');
$dog = new Cachorro('Rex', $ana);
echo "Dono: " . $dog->getDono();
echo "\nNome do dono: " . $dog->getDono()->getNome();

See working on ideone .

Note that I had the owner and owner's name printed. By chance the result is the same, but take it as a mere chance. In the future each technique may give different results.

As you want to learn I will take advantage to tell you to avoid obvious comments like saying that class is Cliente is class Cliente . See how obvious it is? Comments should tell you why and not what .

Also try to keep the code with consistent organization. It may sound silly but it is critical to do this. You visualize better. People who will work with your code, including here, visualize better. You get to organize your thoughts in a more organized way.

I'm saying this because it does not seem to be your case but there are beginner programmers who are stubborn, who think this is silly. And they spend their whole lives doing everything wrong and never learn to make quality code. I never knew in my more than 30 years of experience a single good programmer who did not worry about these details. There are even those who argue that the site should serve users in any way, without organization. These people do not understand that they are doing a disservice to users. They are not helping programmers evolve as needed. Originally the goal of StackExchange sites network was to make everyone learn, to be different from the forums that only gave solutions. And then the programmers look like the last chart page (according to my experience the graphics seem to me quite close to reality in most cases).

I'm not a fan of the term attribute, I prefer field .

    
29.12.2014 / 12:05
7

You are adding a Object (Client class) to $ana

$ana = new Cliente('ana');

So here $this->dono = $dono; gets an object (not a string )

public function __construct($nome,$dono){
   $this->nome  = $nome;
   $this->dono  = $dono;
}

At the moment you try to print with echo method getDono() it will send the variable $this->dono that you previously set as the "class Ana" (an object)

public function getDono(){
    return $this->dono; //Retorna o objeto
}

The correct would look like this:

echo "Dono: ". $dog->getDono()->nome;

Or so:

$ana = new Cliente('ana');
$dog = new Cachorro('Rex', $ana->nome);
echo "Dono: ". $dog->getDono();

You can also make the variable name in private (or protected ) and create a method to catch it, thus preventing accidentally someone seven a value out of the class:

class Cliente {
    private $nome;

    public function __construct($nome){
        $this->nome     = $nome;
    }

    public function getNome(){
        return $this->nome;
    }
}

and use it this way:

$ana = new Cliente('ana');
$dog = new Cachorro('Rex', $ana->getNome());
echo "Dono: ". $dog->getDono();
    
29.12.2014 / 05:38
5

Try adding a __toString method to your class Cliente , type:

public function __toString() {
    return $this->nome;
}

So you can pass $ana instead of 'ana' smoothly:

$ana = new Cliente('ana');
$dog = new Cachorro('Rex', $ana);
echo "Dono: ". $dog->getDono();
    
29.12.2014 / 05:39