In the specialized class should I use self or Parent to access the variables?

Asked

Viewed 168 times

4

I have two classes, one abstract (Connector) and a specialized class (Connectorwmi) extending from Connector.

My question is, considering the code below, in the specialized class I should rather than call self::$connection, call for Parent::$connection and **Parent::$mensagemErro?

Abstract class:

abstract class Conector
{
    /**
     * Recurso de conexão externa
     * 
     * @var object
     */
    protected static $conexao;

    /**
     * Mensagem de erro
     * 
     * @var string
     */
    protected static $mensagemErro;

    /**
     * Realiza conexão com o host alvo
     * 
     * @param   string  $host
     * @param   string  $usuario
     * @param   string  $senha
     * @param   int     $porta
     * @param   int     $timeout
     * @return  void
     */
    abstract public static function conectar($host, $usuario = null, $senha = null, $porta = 135, $timeout = 10);

    /**
     * Consulta o status da conexão
     * 
     * @return bool
     */
    public static function status()
    {
        return (self::$conexao !== NULL) ? TRUE : FALSE;
    }

    /**
     * Retorna mensagem de erro gerada durante a tentativa de conexão 
     * ou erro gerado na chamada do método "executar"
     * 
     * @return string
     */
    public static function mensagemErro()
    {
        return self::$mensagemErro;
    }

    /**
     * Executa a instrução remotamente
     * 
     * @param   string $instrucao
     * @return  object
     */
    abstract public static function executar($instrucao);
}

Main class:

class ConectorWmi extends Conector
{    
    /**
     * Estabelece conexão com máquinas Windows via chamada COM
     * 
     * @param   string  $host
     * @param   string  $usuario
     * @param   string  $senha
     * @param   int     $porta
     * @param   int     $timeout
     * @return  void
     */
    public static function conectar($host, $usuario = null, $senha = null, $porta = 135, $timeout = 10)
    {
        try
        {
            /**
             * Testa conectividade com host alvo
             * 
             * @param string $host
             * @param string $porta
             * @param int    $errno   valor de sistema
             * @param string $errstr  mensagem de sistema
             * @param int    $timeout tempo máximo a esperar
             */    
            if (!$socket = @fsockopen($host, $porta, $errno, $errstr, $timeout))
            {
                // @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
                $dic = [
                            10056 => "Já existe uma conexão socket aberta para o host <b>{$host}</b>!",
                            10057 => "Não foi possível conectar ao socket na chamada do host <b>{$host}</b>!",
                            10060 => "Time Out na chamada do host <b>{$host}</b>!",
                            10061 => "O host <b>{$host}</b> recusou a conexão!",
                        ];

                $mensagem = (array_key_exists($errno, $dic)) ? strtr($errno, $dic) : $errstr;          

                throw new RuntimeException("Erro ({$errno}): {$mensagem}");
            }

            fclose($socket); // Fecha o socket aberto anteriormente

            $WbemLocator = new COM("WbemScripting.SWbemLocator");
            // @see https://msdn.microsoft.com/en-us/library/aa393720(v=vs.85).aspx
            self::$conexao = $WbemLocator->ConnectServer($host, 'root\cimv2', $usuario, $senha, 'MS_416');
            self::$conexao->Security_->ImpersonationLevel = 3;
        }
        catch (com_exception $e) {
            self::$mensagemErro = utf8_encode($e->getMessage());
        }
        catch (RuntimeException $e) {
            self::$mensagemErro = $e->getMessage();
        }
        catch (Exception $e) {
            self::$mensagemErro =  $e->getMessage();
        }
    }

    /**
     * Executa a instrução remotamente
     * 
     * @param   string $instrucao
     * @return  object
     */
    public static function executar($instrucao)
    {
        try
        {
            if (!self::$conexao)
            {
                throw new RuntimeException("Erro: É necessário abrir uma conexão antes de tentar executar qualquer comando!");
            }
             // @see http://php.net/manual/en/ref.com.php
            return self::$conexao->ExecQuery($instrucao);
        }
        catch (RuntimeException $e) {
            return $e->getMessage();
        }
    }
}

And in the specialized class, would be important or recommended gives a Return in the status and messaging method?

public static function status()
{
    return parent::status();
}

public static function mensagemErro()
{
    return parent::mensagemErro();
}
  • 1

    Parent vc usually uses when you need to "go up" to the implementation of who you inherited (in case you are reimplementing). For example, your "wipeRegisters()" does something specific, but calls Parent:wipeRegisters() to complete the procedure with what the base implementation would already do. Under normal conditions it’s always self.

  • 1

    One apart @Bacco and Fábio, and to give reason to Bacco. If the mother class were not abstract it would always be $this-> , which is the equivalent of self, if there is no reimplementation in the daughter class the mother class method is called

  • I changed this static strategy to: http://answall.com/questions/166611/qual-a-bestaddressingpara-lidar-com-coded

1 answer

4

For some tests I’ve done it’s relevant to use parent:: if in the abstract class and in the one that extends it there is a method with the same name and wants to call the method of the mother class (abstract), ex:

<?php
abstract class hey {
    protected function hello() {
        echo 'hello from hey';
    }
}
class lol extends hey {
    protected function hello() {
        echo 'hello from lol';
    }
    public function do_hello() {
        self::hello();
        parent::hello();
    }
}
$lol = new lol();
$lol->do_hello();

DEMONSTRATION

But if there isn’t (be sure there isn’t a method with the same name), you can restrict yourself to self:: that this one goes looking for the method in the class where it is called and if not found will look in the class Parent (abstract), e.g.:

<?php
abstract class hey {
    protected function hello() {
        echo 'hello from hey';
    }
}
class lol extends hey {
    protected function adeus() {
        echo 'hello from lol';
    }
    public function do_hello() {
        self::hello();
        parent::hello();
    }
}
$lol = new lol();
$lol->do_hello();

DEMONSTRATION

as you can see both executed the method of the abstract class hey, and not that of lol, because lol has no method hello().

BUT, in the case of PHP, for the sake of readability and if your intention is to call the method/variable of the mother class even if a/o has reprinted in the daughter I would parent::$conexao

However I find it unessential to create methods to access these variables of the mother class, being able only parent::$status and parent::$mensagemErro where necessary.

  • I understood. In terms of good practice, it would still be recommended to call in the class that extended Connect Messaging Methods and Status? Just to make it visible (as I asked in the question), or it would not be advisable?

Browser other questions tagged

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