Type induction for any type of object

Asked

Viewed 156 times

5

I am wanting to make a method of a certain class accept an object as a parameter. However, this object could be of any type. Example:

class classeExemplo
{
    public function meuMetodo(Object $objeto)
    {
        // Seguiria aqui o bloco de código
    }
}

// Instanciando meus objetos
$produto = new Produto();
$usuario = new Usuario();

/* alimentaria meus objetos com suas respectivas informações */

// Instaciando minha classe que tem o método que recebe qualquer tipo de Objeto
$exemplo = new classeExemplo();

// Chamando o método passando objetos diferentes
$exemplo->meuMetodo($produto);
$exemplo->meuMetodo($usuario);

That obviously doesn’t work. Has anyone ever found themselves in a similar situation? How could I get around and somehow make it work?

  • Have you tried using an abstract class encapsulating the other ones? Or do you really need to be any kind of object (including PHP’s own classes)?

  • Not necessarily the PHP classes themselves, because I didn’t analyze at this point, only the classes I created myself.

5 answers

5


PHP is a dynamic language. Its normal is to accept any type, so just do not specify any type that will be accepted:

class Produto{}
class Usuario {}
class classeExemplo
{
    public function meuMetodo($objeto) //<======== mudei aqui
    {
        // Seguiria aqui o bloco de código
    }
}

// Instanciando meus objetos
$produto = new Produto();
$usuario = new Usuario();

/* alimentaria meus objetos com suas respectivas informações */

// Instaciando minha classe que tem o método que recebe qualquer tipo de Objeto
$exemplo = new classeExemplo();

// Chamando o método passando objetos diferentes
$exemplo->meuMetodo($produto);
$exemplo->meuMetodo($usuario);

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

2

Although what you’re trying doesn’t make sense (in any language), below is as close as you can get:

class classeExemplo
{
    public function meuMetodo($objeto)
    {
        if (!is_object($objeto)) {
            throw new InvalidArgumentException("Not an object!");            
        }

        print "ok\n";
    }
}
  • Thank you for the @felipsmartins reply. But I don’t understand why it doesn’t make sense to want to induce the type of data in the parameter, as we do with array. And "(in no language)", - if I am not mistaken - in C# we can induce the parameter to be object with "... (Object $objectName){}"

1

Currently it is not possible to define types, because the PHP standard accepts any type, but adding the prefix Object to the argument, you’re not exactly declaring the type for that argument, you’re declaring the instance to which that object should belong.

<?php
class Teste
{
    public function show(Object $arg)
    {   
        return $arg;
    }
}
class Object {}
$objecto = (object) 'Teste';
// $objecto = new stdClass();

$teste = new Teste();
var_dump($teste->show(new Object)); # funciona (instancia de Object)
var_dump($teste->show($objecto)); # não funciona (instancia de stdClass)

?>

To solve this just don’t give a prefix to the argument in question, and everything will work out just fine.

<?php
...
public function show($arg)
        {   
            return $arg;
        }
...
?>

But if you really want to define a specific type for that argument, or a requirement for that particular argument, you should then work on that argument in order to create that rule.

Another example would be this:

<?php

class Teste
{
    public function show($object=null)
    {
        if(!empty($object) && gettype($object) === 'object'){
            if(!($object instanceof stdClass)){
                return  "Retorno: \"{$object}\" é um objecto <br/>";
            }
            throw new Exception('é um objecto, mas não pode ser retornado como string');
        }
        throw new Exception("\"{$object}\" é " . gettype($object));
    }
}
class Object
{
    protected $nome;
    public function __construct($nome=null){
        $this->nome = $nome;
    }
    public function __toString(){
        if(!empty($this->nome)){
            return $this->nome;
        }
        return 'default';
    }
}

$teste = new Teste();
try{
    // print $teste->show(new stdClass());
    print $teste->show(new Object('LMAO'));
    // print $teste->show(new Object());
    // print $teste->show(1);
    // print $teste->show('teste');
    // print $teste->show(0.01);
} catch (Exception $e){
    print 'Excepção: ' . $e->getMessage();
}

?>

It shall simply make an exception where the panel is not an object, or where it is a stdClass.

Currently it is possible to pass arguments by reference, and also specify types of returns for functions, if you want to know more, you can follow this link and browse through the categories "Funcions" and "Clases and Objects". Of course, if you look further, you can still find other good suggestions, there’s plenty.

0

In addition to the methods presented in the other answers, you can create a class encompassing the others you want to pass in this parameter:

Code:

abstract class FooBar {
   public $name;
}

class Foo extends FooBar {
   public $name = "Foo";
}

class Bar extends FooBar {
   public $name = "Bar";
}

class Outra{
   public $name = "Outra";
}

class Teste {
   public function testar(FooBar $obj){
      echo $obj->name;
   }
}


$teste = new Teste();

$foo = new Foo();
$bar = new Bar();

$out = new Outra();

$teste->testar($foo);
echo PHP_EOL;
$teste->testar($bar);
echo PHP_EOL;
$teste->testar($out);

Exit:

Foo
Bar
<br />
<b>Catchable fatal error</b>:  Argument 1 passed to Teste::testar() must be an instance of FooBar, instance of Outra given, called in [...][...] on line 37 and defined in <b>[...][...]</b> on line <b>20</b><br />

0

This technique you refer to is called overloading. This concept does not exist in PHP. If you try to define two methods with the same name but with different arguments, you will have a syntax error.

What you can do is this:

public function meuMetodo($argumento)
{
    if ($argumento instanceof Produto) {
        // ...
    }
    elseif ($argumento instanceof Usuario) {
        // ...
    }
    else {
        throw new \Exception('Tipo de argumento inválido.');
    }
}

You can also use a block switch:

public function meuMetodo($object argumento)
{
    switch(get_class($argumento)) {
        case 'Produto':
            // ...
            break;
        case 'Usuario':
            // ...
            break;
        default:
            throw new \Exception('Tipo de argumento inválido.');
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.